1    /*******************************************************/
2    /*      "C" Language Integrated Production System      */
3    /*                                                     */
4    /*             CLIPS Version 6.30  01/25/15            */
5    /*                                                     */
6    /*                  DEFGLOBAL MODULE                   */
7    /*******************************************************/
8 
9 /*************************************************************/
10 /* Purpose: Provides core routines for the creation and      */
11 /*   maintenance of the defglobal construct.                 */
12 /*                                                           */
13 /* Principal Programmer(s):                                  */
14 /*      Gary D. Riley                                        */
15 /*                                                           */
16 /* Contributing Programmer(s):                               */
17 /*      Brian L. Dantes                                      */
18 /*                                                           */
19 /* Revision History:                                         */
20 /*                                                           */
21 /*      6.23: Correction for FalseSymbol/TrueSymbol. DR0859  */
22 /*                                                           */
23 /*      6.24: Renamed BOOLEAN macro type to intBool.         */
24 /*                                                           */
25 /*            Corrected code to remove run-time program      */
26 /*            compiler warning.                              */
27 /*                                                           */
28 /*      6.30: Removed conditional code for unsupported       */
29 /*            compilers/operating systems (IBM_MCW,          */
30 /*            MAC_MCW, and IBM_TBC).                         */
31 /*                                                           */
32 /*            Changed garbage collection algorithm.          */
33 /*                                                           */
34 /*            Added const qualifiers to remove C++           */
35 /*            deprecation warnings.                          */
36 /*                                                           */
37 /*            Converted API macros to function calls.        */
38 /*                                                           */
39 /*            Fixed linkage issue when BLOAD_ONLY compiler   */
40 /*            flag is set to 1.                              */
41 /*                                                           */
42 /*            Changed find construct functionality so that   */
43 /*            imported modules are search when locating a    */
44 /*            named construct.                               */
45 /*                                                           */
46 /*************************************************************/
47 
48 #define _GLOBLDEF_SOURCE_
49 
50 #include "setup.h"
51 
52 #if DEFGLOBAL_CONSTRUCT
53 
54 #include <stdio.h>
55 #define _STDIO_INCLUDED_
56 
57 #include "memalloc.h"
58 #include "modulpsr.h"
59 #include "multifld.h"
60 #include "router.h"
61 #include "strngrtr.h"
62 #include "modulutl.h"
63 #include "globlbsc.h"
64 #include "globlpsr.h"
65 #include "globlcom.h"
66 #include "utility.h"
67 #include "commline.h"
68 #include "envrnmnt.h"
69 
70 #if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
71 #include "bload.h"
72 #include "globlbin.h"
73 #endif
74 
75 #if CONSTRUCT_COMPILER && (! RUN_TIME)
76 #include "globlcmp.h"
77 #endif
78 
79 #include "globldef.h"
80 
81 /***************************************/
82 /* LOCAL INTERNAL FUNCTION DEFINITIONS */
83 /***************************************/
84 
85    static void                   *AllocateModule(void *);
86    static void                    ReturnModule(void *,void *);
87    static void                    ReturnDefglobal(void *,void *);
88    static void                    InitializeDefglobalModules(void *);
89    static intBool                 GetDefglobalValue2(void *,void *,DATA_OBJECT_PTR);
90    static void                    IncrementDefglobalBusyCount(void *,void *);
91    static void                    DecrementDefglobalBusyCount(void *,void *);
92    static void                    DeallocateDefglobalData(void *);
93    static void                    DestroyDefglobalAction(void *,struct constructHeader *,void *);
94 #if (! BLOAD_ONLY)
95    static void                    DestroyDefglobal(void *,void *);
96 #endif
97 
98 /**************************************************************/
99 /* InitializeDefglobals: Initializes the defglobal construct. */
100 /**************************************************************/
InitializeDefglobals(void * theEnv)101 globle void InitializeDefglobals(
102   void *theEnv)
103   {
104    struct entityRecord globalInfo = { "GBL_VARIABLE", GBL_VARIABLE,0,0,0,
105                                                        NULL,
106                                                        NULL,
107                                                        NULL,
108                                                        GetDefglobalValue2,
109                                                        NULL,NULL,
110                                                        NULL,NULL,NULL,NULL,NULL,NULL };
111 
112    struct entityRecord defglobalPtrRecord = { "DEFGLOBAL_PTR", DEFGLOBAL_PTR,0,0,0,
113                                                        NULL,NULL,NULL,
114                                                        QGetDefglobalValue,
115                                                        NULL,
116                                                        DecrementDefglobalBusyCount,
117                                                        IncrementDefglobalBusyCount,
118                                                        NULL,NULL,NULL,NULL,NULL };
119 
120    AllocateEnvironmentData(theEnv,DEFGLOBAL_DATA,sizeof(struct defglobalData),DeallocateDefglobalData);
121 
122    memcpy(&DefglobalData(theEnv)->GlobalInfo,&globalInfo,sizeof(struct entityRecord));
123    memcpy(&DefglobalData(theEnv)->DefglobalPtrRecord,&defglobalPtrRecord,sizeof(struct entityRecord));
124 
125    DefglobalData(theEnv)->ResetGlobals = TRUE;
126    DefglobalData(theEnv)->LastModuleIndex = -1;
127 
128    InstallPrimitive(theEnv,&DefglobalData(theEnv)->GlobalInfo,GBL_VARIABLE);
129    InstallPrimitive(theEnv,&DefglobalData(theEnv)->DefglobalPtrRecord,DEFGLOBAL_PTR);
130 
131    InitializeDefglobalModules(theEnv);
132 
133    DefglobalBasicCommands(theEnv);
134    DefglobalCommandDefinitions(theEnv);
135 
136    DefglobalData(theEnv)->DefglobalConstruct =
137       AddConstruct(theEnv,"defglobal","defglobals",ParseDefglobal,EnvFindDefglobal,
138                    GetConstructNamePointer,GetConstructPPForm,
139                    GetConstructModuleItem,EnvGetNextDefglobal,SetNextConstruct,
140                    EnvIsDefglobalDeletable,EnvUndefglobal,ReturnDefglobal);
141   }
142 
143 /****************************************************/
144 /* DeallocateDefglobalData: Deallocates environment */
145 /*    data for the defglobal construct.             */
146 /****************************************************/
DeallocateDefglobalData(void * theEnv)147 static void DeallocateDefglobalData(
148   void *theEnv)
149   {
150 #if ! RUN_TIME
151    struct defglobalModule *theModuleItem;
152    void *theModule;
153 
154 #if BLOAD || BLOAD_AND_BSAVE
155    if (Bloaded(theEnv)) return;
156 #endif
157 
158    DoForAllConstructs(theEnv,DestroyDefglobalAction,DefglobalData(theEnv)->DefglobalModuleIndex,FALSE,NULL);
159 
160    for (theModule = EnvGetNextDefmodule(theEnv,NULL);
161         theModule != NULL;
162         theModule = EnvGetNextDefmodule(theEnv,theModule))
163      {
164       theModuleItem = (struct defglobalModule *)
165                       GetModuleItem(theEnv,(struct defmodule *) theModule,
166                                     DefglobalData(theEnv)->DefglobalModuleIndex);
167       rtn_struct(theEnv,defglobalModule,theModuleItem);
168      }
169 #else
170    DoForAllConstructs(theEnv,DestroyDefglobalAction,DefglobalData(theEnv)->DefglobalModuleIndex,FALSE,NULL);
171 #endif
172   }
173 
174 /***************************************************/
175 /* DestroyDefglobalAction: Action used to remove   */
176 /*   defglobals as a result of DestroyEnvironment. */
177 /***************************************************/
DestroyDefglobalAction(void * theEnv,struct constructHeader * theConstruct,void * buffer)178 static void DestroyDefglobalAction(
179   void *theEnv,
180   struct constructHeader *theConstruct,
181   void *buffer)
182   {
183 #if MAC_XCD
184 #pragma unused(buffer)
185 #endif
186 #if (! BLOAD_ONLY)
187    struct defglobal *theDefglobal = (struct defglobal *) theConstruct;
188 
189    if (theDefglobal == NULL) return;
190 
191    DestroyDefglobal(theEnv,theDefglobal);
192 #else
193 #if MAC_XCD
194 #pragma unused(theEnv,theConstruct)
195 #endif
196 #endif
197   }
198 
199 /*********************************************************/
200 /* InitializeDefglobalModules: Initializes the defglobal */
201 /*   construct for use with the defmodule construct.     */
202 /*********************************************************/
InitializeDefglobalModules(void * theEnv)203 static void InitializeDefglobalModules(
204   void *theEnv)
205   {
206    DefglobalData(theEnv)->DefglobalModuleIndex = RegisterModuleItem(theEnv,"defglobal",
207                                     AllocateModule,
208                                     ReturnModule,
209 #if BLOAD_AND_BSAVE || BLOAD || BLOAD_ONLY
210                                     BloadDefglobalModuleReference,
211 #else
212                                     NULL,
213 #endif
214 #if CONSTRUCT_COMPILER && (! RUN_TIME)
215                                     DefglobalCModuleReference,
216 #else
217                                     NULL,
218 #endif
219                                     EnvFindDefglobalInModule);
220 
221 #if (! BLOAD_ONLY) && (! RUN_TIME) && DEFMODULE_CONSTRUCT
222    AddPortConstructItem(theEnv,"defglobal",SYMBOL);
223 #endif
224   }
225 
226 /*************************************************/
227 /* AllocateModule: Allocates a defglobal module. */
228 /*************************************************/
AllocateModule(void * theEnv)229 static void *AllocateModule(
230   void *theEnv)
231   {
232    return((void *) get_struct(theEnv,defglobalModule));
233   }
234 
235 /***********************************************/
236 /* ReturnModule: Deallocates a defglobal module. */
237 /***********************************************/
ReturnModule(void * theEnv,void * theItem)238 static void ReturnModule(
239   void *theEnv,
240   void *theItem)
241   {
242    FreeConstructHeaderModule(theEnv,(struct defmoduleItemHeader *) theItem,DefglobalData(theEnv)->DefglobalConstruct);
243    rtn_struct(theEnv,defglobalModule,theItem);
244   }
245 
246 /**************************************************************/
247 /* GetDefglobalModuleItem: Returns a pointer to the defmodule */
248 /*  item for the specified defglobal or defmodule.            */
249 /**************************************************************/
GetDefglobalModuleItem(void * theEnv,struct defmodule * theModule)250 globle struct defglobalModule *GetDefglobalModuleItem(
251   void *theEnv,
252   struct defmodule *theModule)
253   {
254    return((struct defglobalModule *) GetConstructModuleItemByIndex(theEnv,theModule,DefglobalData(theEnv)->DefglobalModuleIndex));
255   }
256 
257 /*****************************************************/
258 /* EnvFindDefglobal: Searches for a defglobal in the */
259 /*   list of defglobals. Returns a pointer to the    */
260 /*   defglobal if found, otherwise NULL.             */
261 /*****************************************************/
EnvFindDefglobal(void * theEnv,const char * defglobalName)262 globle void *EnvFindDefglobal(
263   void *theEnv,
264   const char *defglobalName)
265   {
266    return(FindNamedConstructInModuleOrImports(theEnv,defglobalName,DefglobalData(theEnv)->DefglobalConstruct));
267   }
268 
269 /*****************************************************/
270 /* EnvFindDefglobalInModule: Searches for a defglobal in the */
271 /*   list of defglobals. Returns a pointer to the    */
272 /*   defglobal if found, otherwise NULL.             */
273 /*****************************************************/
EnvFindDefglobalInModule(void * theEnv,const char * defglobalName)274 globle void *EnvFindDefglobalInModule(
275   void *theEnv,
276   const char *defglobalName)
277   {
278    return(FindNamedConstructInModule(theEnv,defglobalName,DefglobalData(theEnv)->DefglobalConstruct));
279   }
280 
281 /********************************************************************/
282 /* EnvGetNextDefglobal: If passed a NULL pointer, returns the first */
283 /*   defglobal in the defglobal list. Otherwise returns the next    */
284 /*   defglobal following the defglobal passed as an argument.       */
285 /********************************************************************/
EnvGetNextDefglobal(void * theEnv,void * defglobalPtr)286 globle void *EnvGetNextDefglobal(
287   void *theEnv,
288   void *defglobalPtr)
289   {
290    return((void *) GetNextConstructItem(theEnv,(struct constructHeader *) defglobalPtr,DefglobalData(theEnv)->DefglobalModuleIndex));
291   }
292 
293 /*********************************************************/
294 /* EnvIsDefglobalDeletable: Returns TRUE if a particular */
295 /*   defglobal can be deleted, otherwise returns FALSE.  */
296 /*********************************************************/
EnvIsDefglobalDeletable(void * theEnv,void * ptr)297 globle intBool EnvIsDefglobalDeletable(
298   void *theEnv,
299   void *ptr)
300   {
301    if (! ConstructsDeletable(theEnv))
302      { return FALSE; }
303 
304    if (((struct defglobal *) ptr)->busyCount) return(FALSE);
305 
306    return(TRUE);
307   }
308 
309 /************************************************************/
310 /* ReturnDefglobal: Returns the data structures associated  */
311 /*   with a defglobal construct to the pool of free memory. */
312 /************************************************************/
ReturnDefglobal(void * theEnv,void * vTheDefglobal)313 static void ReturnDefglobal(
314   void *theEnv,
315   void *vTheDefglobal)
316   {
317 #if (! BLOAD_ONLY) && (! RUN_TIME)
318    struct defglobal *theDefglobal = (struct defglobal *) vTheDefglobal;
319 
320    if (theDefglobal == NULL) return;
321 
322    /*====================================*/
323    /* Return the global's current value. */
324    /*====================================*/
325 
326    ValueDeinstall(theEnv,&theDefglobal->current);
327    if (theDefglobal->current.type == MULTIFIELD)
328      { ReturnMultifield(theEnv,(struct multifield *) theDefglobal->current.value); }
329 
330    /*================================================*/
331    /* Return the expression representing the initial */
332    /* value of the defglobal when it was defined.    */
333    /*================================================*/
334 
335    RemoveHashedExpression(theEnv,theDefglobal->initial);
336 
337    /*===============================*/
338    /* Release items stored in the   */
339    /* defglobal's construct header. */
340    /*===============================*/
341 
342    DeinstallConstructHeader(theEnv,&theDefglobal->header);
343 
344    /*======================================*/
345    /* Return the defglobal data structure. */
346    /*======================================*/
347 
348    rtn_struct(theEnv,defglobal,theDefglobal);
349 
350    /*===========================================*/
351    /* Set the variable indicating that a change */
352    /* has been made to a global variable.       */
353    /*===========================================*/
354 
355    DefglobalData(theEnv)->ChangeToGlobals = TRUE;
356 #endif
357   }
358 
359 /************************************************************/
360 /* DestroyDefglobal: Returns the data structures associated  */
361 /*   with a defglobal construct to the pool of free memory. */
362 /************************************************************/
363 #if (! BLOAD_ONLY)
DestroyDefglobal(void * theEnv,void * vTheDefglobal)364 static void DestroyDefglobal(
365   void *theEnv,
366   void *vTheDefglobal)
367   {
368    struct defglobal *theDefglobal = (struct defglobal *) vTheDefglobal;
369 
370    if (theDefglobal == NULL) return;
371 
372    /*====================================*/
373    /* Return the global's current value. */
374    /*====================================*/
375 
376    if (theDefglobal->current.type == MULTIFIELD)
377      { ReturnMultifield(theEnv,(struct multifield *) theDefglobal->current.value); }
378 
379 #if (! RUN_TIME)
380 
381    /*===============================*/
382    /* Release items stored in the   */
383    /* defglobal's construct header. */
384    /*===============================*/
385 
386    DeinstallConstructHeader(theEnv,&theDefglobal->header);
387 
388    /*======================================*/
389    /* Return the defglobal data structure. */
390    /*======================================*/
391 
392    rtn_struct(theEnv,defglobal,theDefglobal);
393 #endif
394   }
395 #endif
396 
397 /************************************************/
398 /* QSetDefglobalValue: Lowest level routine for */
399 /*   setting a defglobal's value.               */
400 /************************************************/
QSetDefglobalValue(void * theEnv,struct defglobal * theGlobal,DATA_OBJECT_PTR vPtr,int resetVar)401 globle void QSetDefglobalValue(
402   void *theEnv,
403   struct defglobal *theGlobal,
404   DATA_OBJECT_PTR vPtr,
405   int resetVar)
406   {
407    /*====================================================*/
408    /* If the new value passed for the defglobal is NULL, */
409    /* then reset the defglobal to the initial value it   */
410    /* had when it was defined.                           */
411    /*====================================================*/
412 
413    if (resetVar)
414      {
415       EvaluateExpression(theEnv,theGlobal->initial,vPtr);
416       if (EvaluationData(theEnv)->EvaluationError)
417         {
418          vPtr->type = SYMBOL;
419          vPtr->value = EnvFalseSymbol(theEnv);
420         }
421      }
422 
423    /*==========================================*/
424    /* If globals are being watch, then display */
425    /* the change to the global variable.       */
426    /*==========================================*/
427 
428 #if DEBUGGING_FUNCTIONS
429    if (theGlobal->watch)
430      {
431       EnvPrintRouter(theEnv,WTRACE,":== ?*");
432       EnvPrintRouter(theEnv,WTRACE,ValueToString(theGlobal->header.name));
433       EnvPrintRouter(theEnv,WTRACE,"* ==> ");
434       PrintDataObject(theEnv,WTRACE,vPtr);
435       EnvPrintRouter(theEnv,WTRACE," <== ");
436       PrintDataObject(theEnv,WTRACE,&theGlobal->current);
437       EnvPrintRouter(theEnv,WTRACE,"\n");
438      }
439 #endif
440 
441    /*==============================================*/
442    /* Remove the old value of the global variable. */
443    /*==============================================*/
444 
445    ValueDeinstall(theEnv,&theGlobal->current);
446    if (theGlobal->current.type == MULTIFIELD)
447      { ReturnMultifield(theEnv,(struct multifield *) theGlobal->current.value); }
448 
449    /*===========================================*/
450    /* Set the new value of the global variable. */
451    /*===========================================*/
452 
453    theGlobal->current.type = vPtr->type;
454    if (vPtr->type != MULTIFIELD) theGlobal->current.value = vPtr->value;
455    else DuplicateMultifield(theEnv,&theGlobal->current,vPtr);
456    ValueInstall(theEnv,&theGlobal->current);
457 
458    /*===========================================*/
459    /* Set the variable indicating that a change */
460    /* has been made to a global variable.       */
461    /*===========================================*/
462 
463    DefglobalData(theEnv)->ChangeToGlobals = TRUE;
464 
465    if ((UtilityData(theEnv)->CurrentGarbageFrame->topLevel) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) &&
466        (EvaluationData(theEnv)->CurrentExpression == NULL) && (UtilityData(theEnv)->GarbageCollectionLocks == 0))
467      {
468       CleanCurrentGarbageFrame(theEnv,NULL);
469       CallPeriodicTasks(theEnv);
470      }
471   }
472 
473 /**************************************************************/
474 /* QFindDefglobal: Searches for a defglobal in the list of    */
475 /*   defglobals. Returns a pointer to the defglobal if found, */
476 /*   otherwise NULL.                                          */
477 /**************************************************************/
QFindDefglobal(void * theEnv,SYMBOL_HN * defglobalName)478 globle struct defglobal *QFindDefglobal(
479   void *theEnv,
480   SYMBOL_HN *defglobalName)
481   {
482    struct defglobal *theDefglobal;
483 
484    for (theDefglobal = (struct defglobal *) EnvGetNextDefglobal(theEnv,NULL);
485         theDefglobal != NULL;
486         theDefglobal = (struct defglobal *) EnvGetNextDefglobal(theEnv,theDefglobal))
487      { if (defglobalName == theDefglobal->header.name) return (theDefglobal); }
488 
489    return(NULL);
490   }
491 
492 /*********************************************************************/
493 /* EnvGetDefglobalValueForm: Returns the pretty print representation */
494 /*   of the current value of the specified defglobal. For example,   */
495 /*   if the current value of ?*x* is 5, the string "?*x* = 5" would  */
496 /*   be returned.                                                    */
497 /*********************************************************************/
EnvGetDefglobalValueForm(void * theEnv,char * buffer,size_t bufferLength,void * vTheGlobal)498 globle void EnvGetDefglobalValueForm(
499   void *theEnv,
500   char *buffer,
501   size_t bufferLength,
502   void *vTheGlobal)
503   {
504    struct defglobal *theGlobal = (struct defglobal *) vTheGlobal;
505 
506    OpenStringDestination(theEnv,"GlobalValueForm",buffer,bufferLength);
507    EnvPrintRouter(theEnv,"GlobalValueForm","?*");
508    EnvPrintRouter(theEnv,"GlobalValueForm",ValueToString(theGlobal->header.name));
509    EnvPrintRouter(theEnv,"GlobalValueForm","* = ");
510    PrintDataObject(theEnv,"GlobalValueForm",&theGlobal->current);
511    CloseStringDestination(theEnv,"GlobalValueForm");
512   }
513 
514 /************************************************************/
515 /* EnvGetGlobalsChanged: Returns the defglobal change flag. */
516 /************************************************************/
EnvGetGlobalsChanged(void * theEnv)517 globle int EnvGetGlobalsChanged(
518   void *theEnv)
519   {
520    return(DefglobalData(theEnv)->ChangeToGlobals);
521   }
522 
523 /*********************************************************/
524 /* EnvSetGlobalsChanged: Sets the defglobal change flag. */
525 /*********************************************************/
EnvSetGlobalsChanged(void * theEnv,int value)526 globle void EnvSetGlobalsChanged(
527   void *theEnv,
528   int value)
529   {
530    DefglobalData(theEnv)->ChangeToGlobals = value;
531   }
532 
533 /**********************************************************/
534 /* GetDefglobalValue2: Returns the value of the specified */
535 /*   global variable in the supplied DATA_OBJECT.         */
536 /**********************************************************/
GetDefglobalValue2(void * theEnv,void * theValue,DATA_OBJECT_PTR vPtr)537 static intBool GetDefglobalValue2(
538   void *theEnv,
539   void *theValue,
540   DATA_OBJECT_PTR vPtr)
541   {
542    struct defglobal *theGlobal;
543    int count;
544 
545    /*===========================================*/
546    /* Search for the specified defglobal in the */
547    /* modules visible to the current module.    */
548    /*===========================================*/
549 
550    theGlobal = (struct defglobal *)
551                FindImportedConstruct(theEnv,"defglobal",NULL,ValueToString(theValue),
552                &count,TRUE,NULL);
553 
554    /*=============================================*/
555    /* If it wasn't found, print an error message. */
556    /*=============================================*/
557 
558    if (theGlobal == NULL)
559      {
560       PrintErrorID(theEnv,"GLOBLDEF",1,FALSE);
561       EnvPrintRouter(theEnv,WERROR,"Global variable ?*");
562       EnvPrintRouter(theEnv,WERROR,ValueToString(theValue));
563       EnvPrintRouter(theEnv,WERROR,"* is unbound.\n");
564       vPtr->type = SYMBOL;
565       vPtr->value = EnvFalseSymbol(theEnv);
566       SetEvaluationError(theEnv,TRUE);
567       return(FALSE);
568      }
569 
570    /*========================================================*/
571    /* The current implementation of the defmodules shouldn't */
572    /* allow a construct to be defined which would cause an   */
573    /* ambiguous reference, but we'll check for it anyway.    */
574    /*========================================================*/
575 
576    if (count > 1)
577      {
578       AmbiguousReferenceErrorMessage(theEnv,"defglobal",ValueToString(theValue));
579       vPtr->type = SYMBOL;
580       vPtr->value = EnvFalseSymbol(theEnv);
581       SetEvaluationError(theEnv,TRUE);
582       return(FALSE);
583      }
584 
585    /*=================================*/
586    /* Get the value of the defglobal. */
587    /*=================================*/
588 
589    QGetDefglobalValue(theEnv,theGlobal,vPtr);
590 
591    return(TRUE);
592   }
593 
594 /***************************************************************/
595 /* QGetDefglobalValue: Returns the value of a global variable. */
596 /***************************************************************/
QGetDefglobalValue(void * theEnv,void * vTheGlobal,DATA_OBJECT_PTR vPtr)597 globle int QGetDefglobalValue(
598   void *theEnv,
599   void *vTheGlobal,
600   DATA_OBJECT_PTR vPtr)
601   {
602    struct defglobal *theGlobal = (struct defglobal *) vTheGlobal;
603 
604    /*===============================================*/
605    /* Transfer values which can be copied directly. */
606    /*===============================================*/
607 
608    vPtr->type = theGlobal->current.type;
609    vPtr->value = theGlobal->current.value;
610    vPtr->begin = theGlobal->current.begin;
611    vPtr->end = theGlobal->current.end;
612 
613    /*===========================================================*/
614    /* If the global contains a multifield value, return a copy  */
615    /* of the value so that routines which use this value are    */
616    /* not affected if the value of the global is later changed. */
617    /*===========================================================*/
618 
619    if (vPtr->type == MULTIFIELD)
620      {
621       vPtr->value = EnvCreateMultifield(theEnv,(unsigned long) (vPtr->end + 1));
622       GenCopyMemory(struct field,vPtr->end + 1,
623                                 &((struct multifield *) vPtr->value)->theFields[0],
624                                 &((struct multifield *) theGlobal->current.value)->theFields[theGlobal->current.begin]);
625      }
626 
627    return(TRUE);
628   }
629 
630 /************************************************************/
631 /* EnvGetDefglobalValue: Returns the value of the specified */
632 /*   global variable in the supplied DATA_OBJECT.           */
633 /************************************************************/
EnvGetDefglobalValue(void * theEnv,const char * variableName,DATA_OBJECT_PTR vPtr)634 globle intBool EnvGetDefglobalValue(
635   void *theEnv,
636   const char *variableName,
637   DATA_OBJECT_PTR vPtr)
638   {
639    struct defglobal *theDefglobal;
640 
641    if ((theDefglobal = (struct defglobal *) EnvFindDefglobal(theEnv,variableName)) == NULL)
642      { return(FALSE); }
643 
644    QGetDefglobalValue(theEnv,theDefglobal,vPtr);
645 
646    return(TRUE);
647   }
648 
649 /****************************************************************/
650 /* EnvSetDefglobalValue: Sets the value of the specified global */
651 /*   variable to the value stored in the supplied DATA_OBJECT.  */
652 /****************************************************************/
EnvSetDefglobalValue(void * theEnv,const char * variableName,DATA_OBJECT_PTR vPtr)653 globle intBool EnvSetDefglobalValue(
654   void *theEnv,
655   const char *variableName,
656   DATA_OBJECT_PTR vPtr)
657   {
658    struct defglobal *theGlobal;
659 
660    if ((theGlobal = QFindDefglobal(theEnv,(SYMBOL_HN *) EnvAddSymbol(theEnv,variableName))) == NULL)
661      { return(FALSE); }
662 
663    QSetDefglobalValue(theEnv,theGlobal,vPtr,FALSE);
664 
665    return(TRUE);
666   }
667 
668 /**********************************************************/
669 /* DecrementDefglobalBusyCount: Decrements the busy count */
670 /*   of a defglobal data structure.                       */
671 /**********************************************************/
DecrementDefglobalBusyCount(void * theEnv,void * vTheGlobal)672 static void DecrementDefglobalBusyCount(
673   void *theEnv,
674   void *vTheGlobal)
675   {
676    struct defglobal *theGlobal = (struct defglobal *) vTheGlobal;
677 
678    if (! ConstructData(theEnv)->ClearInProgress) theGlobal->busyCount--;
679   }
680 
681 /**********************************************************/
682 /* IncrementDefglobalBusyCount: Increments the busy count */
683 /*   of a defglobal data structure.                       */
684 /**********************************************************/
IncrementDefglobalBusyCount(void * theEnv,void * vTheGlobal)685 static void IncrementDefglobalBusyCount(
686   void *theEnv,
687   void *vTheGlobal)
688   {
689    struct defglobal *theGlobal = (struct defglobal *) vTheGlobal;
690 #if MAC_XCD
691 #pragma unused(theEnv)
692 #endif
693 
694    theGlobal->busyCount++;
695   }
696 
697 /***********************************************************************/
698 /* UpdateDefglobalScope: Updates the scope flag of all the defglobals. */
699 /***********************************************************************/
UpdateDefglobalScope(void * theEnv)700 globle void UpdateDefglobalScope(
701   void *theEnv)
702   {
703    struct defglobal *theDefglobal;
704    int moduleCount;
705    struct defmodule *theModule;
706    struct defmoduleItemHeader *theItem;
707 
708    /*============================*/
709    /* Loop through every module. */
710    /*============================*/
711 
712    for (theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
713         theModule != NULL;
714         theModule = (struct defmodule *) EnvGetNextDefmodule(theEnv,theModule))
715      {
716       /*============================================================*/
717       /* Loop through every defglobal in the module being examined. */
718       /*============================================================*/
719 
720       theItem = (struct defmoduleItemHeader *)
721                 GetModuleItem(theEnv,theModule,DefglobalData(theEnv)->DefglobalModuleIndex);
722 
723       for (theDefglobal = (struct defglobal *) theItem->firstItem;
724            theDefglobal != NULL ;
725            theDefglobal = (struct defglobal *) EnvGetNextDefglobal(theEnv,theDefglobal))
726         {
727          /*====================================================*/
728          /* If the defglobal is visible to the current module, */
729          /* then mark it as being in scope, otherwise mark it  */
730          /* as being out of scope.                             */
731          /*====================================================*/
732 
733          if (FindImportedConstruct(theEnv,"defglobal",theModule,
734                                    ValueToString(theDefglobal->header.name),
735                                    &moduleCount,TRUE,NULL) != NULL)
736            { theDefglobal->inScope = TRUE; }
737          else
738            { theDefglobal->inScope = FALSE; }
739         }
740      }
741   }
742 
743 /*******************************************************/
744 /* GetNextDefglobalInScope: Returns the next defglobal */
745 /*   that is scope of the current module. Works in a   */
746 /*   similar fashion to GetNextDefglobal, but skips    */
747 /*   defglobals that are out of scope.                 */
748 /*******************************************************/
GetNextDefglobalInScope(void * theEnv,void * vTheGlobal)749 globle void *GetNextDefglobalInScope(
750   void *theEnv,
751   void *vTheGlobal)
752   {
753    struct defglobal *theGlobal = (struct defglobal *) vTheGlobal;
754    struct defmoduleItemHeader *theItem;
755 
756    /*=======================================*/
757    /* If we're beginning the search for the */
758    /* first defglobal in scope, then ...    */
759    /*=======================================*/
760 
761    if (theGlobal == NULL)
762      {
763       /*==============================================*/
764       /* If the current module has been changed since */
765       /* the last time the scopes were computed, then */
766       /* recompute the scopes.                        */
767       /*==============================================*/
768 
769       if (DefglobalData(theEnv)->LastModuleIndex != DefmoduleData(theEnv)->ModuleChangeIndex)
770         {
771          UpdateDefglobalScope(theEnv);
772          DefglobalData(theEnv)->LastModuleIndex = DefmoduleData(theEnv)->ModuleChangeIndex;
773         }
774 
775       /*==========================================*/
776       /* Get the first module and first defglobal */
777       /* to start the search with.                */
778       /*==========================================*/
779 
780       DefglobalData(theEnv)->TheDefmodule = (struct defmodule *) EnvGetNextDefmodule(theEnv,NULL);
781       theItem = (struct defmoduleItemHeader *)
782                 GetModuleItem(theEnv,DefglobalData(theEnv)->TheDefmodule,DefglobalData(theEnv)->DefglobalModuleIndex);
783       theGlobal = (struct defglobal *) theItem->firstItem;
784      }
785 
786    /*==================================================*/
787    /* Otherwise, see if the last defglobal returned by */
788    /* this function has a defglobal following it.      */
789    /*==================================================*/
790 
791    else
792      { theGlobal = (struct defglobal *) EnvGetNextDefglobal(theEnv,theGlobal); }
793 
794    /*======================================*/
795    /* Continue looping through the modules */
796    /* until a defglobal in scope is found. */
797    /*======================================*/
798 
799    while (DefglobalData(theEnv)->TheDefmodule != NULL)
800      {
801       /*=====================================================*/
802       /* Loop through the defglobals in the module currently */
803       /* being examined to see if one is in scope.           */
804       /*=====================================================*/
805 
806       for (;
807            theGlobal != NULL;
808            theGlobal = (struct defglobal *) EnvGetNextDefglobal(theEnv,theGlobal))
809         { if (theGlobal->inScope) return((void *) theGlobal); }
810 
811       /*================================================*/
812       /* If a global in scope couldn't be found in this */
813       /* module, then move on to the next module.       */
814       /*================================================*/
815 
816       DefglobalData(theEnv)->TheDefmodule = (struct defmodule *) EnvGetNextDefmodule(theEnv,DefglobalData(theEnv)->TheDefmodule);
817       theItem = (struct defmoduleItemHeader *)
818                 GetModuleItem(theEnv,DefglobalData(theEnv)->TheDefmodule,DefglobalData(theEnv)->DefglobalModuleIndex);
819       theGlobal = (struct defglobal *) theItem->firstItem;
820      }
821 
822    /*====================================*/
823    /* All the globals in scope have been */
824    /* traversed and there are none left. */
825    /*====================================*/
826 
827    return(NULL);
828   }
829 
830 /*##################################*/
831 /* Additional Environment Functions */
832 /*##################################*/
833 
EnvDefglobalModule(void * theEnv,void * theDefglobal)834 globle const char *EnvDefglobalModule(
835   void *theEnv,
836   void *theDefglobal)
837   {
838    return GetConstructModuleName((struct constructHeader *) theDefglobal);
839   }
840 
EnvGetDefglobalName(void * theEnv,void * theDefglobal)841 globle const char *EnvGetDefglobalName(
842   void *theEnv,
843   void *theDefglobal)
844   {
845    return GetConstructNameString((struct constructHeader *) theDefglobal);
846   }
847 
EnvGetDefglobalPPForm(void * theEnv,void * theDefglobal)848 globle const char *EnvGetDefglobalPPForm(
849   void *theEnv,
850   void *theDefglobal)
851   {
852    return GetConstructPPForm(theEnv,(struct constructHeader *) theDefglobal);
853   }
854 
855 /*#####################################*/
856 /* ALLOW_ENVIRONMENT_GLOBALS Functions */
857 /*#####################################*/
858 
859 #if ALLOW_ENVIRONMENT_GLOBALS
860 
DefglobalModule(void * theDefglobal)861 globle const char *DefglobalModule(
862   void *theDefglobal)
863   {
864    return EnvDefglobalModule(GetCurrentEnvironment(),theDefglobal);
865   }
866 
FindDefglobal(const char * defglobalName)867 globle void *FindDefglobal(
868   const char *defglobalName)
869   {
870    return EnvFindDefglobal(GetCurrentEnvironment(),defglobalName);
871   }
872 
GetDefglobalName(void * theDefglobal)873 globle const char *GetDefglobalName(
874   void *theDefglobal)
875   {
876    return EnvGetDefglobalName(GetCurrentEnvironment(),theDefglobal);
877   }
878 
GetDefglobalPPForm(void * theDefglobal)879 globle const char *GetDefglobalPPForm(
880   void *theDefglobal)
881   {
882    return EnvGetDefglobalPPForm(GetCurrentEnvironment(),theDefglobal);
883   }
884 
GetDefglobalValue(const char * variableName,DATA_OBJECT_PTR vPtr)885 globle intBool GetDefglobalValue(
886   const char *variableName,
887   DATA_OBJECT_PTR vPtr)
888   {
889    return EnvGetDefglobalValue(GetCurrentEnvironment(),variableName,vPtr);
890   }
891 
GetDefglobalValueForm(char * buffer,unsigned bufferLength,void * vTheGlobal)892 globle void GetDefglobalValueForm(
893   char *buffer,
894   unsigned bufferLength,
895   void *vTheGlobal)
896   {
897    EnvGetDefglobalValueForm(GetCurrentEnvironment(),buffer,bufferLength,vTheGlobal);
898   }
899 
GetGlobalsChanged()900 globle int GetGlobalsChanged()
901   {
902    return EnvGetGlobalsChanged(GetCurrentEnvironment());
903   }
904 
GetNextDefglobal(void * defglobalPtr)905 globle void *GetNextDefglobal(
906   void *defglobalPtr)
907   {
908    return EnvGetNextDefglobal(GetCurrentEnvironment(),defglobalPtr);
909   }
910 
IsDefglobalDeletable(void * ptr)911 globle intBool IsDefglobalDeletable(
912   void *ptr)
913   {
914    return EnvIsDefglobalDeletable(GetCurrentEnvironment(),ptr);
915   }
916 
SetDefglobalValue(const char * variableName,DATA_OBJECT_PTR vPtr)917 globle intBool SetDefglobalValue(
918   const char *variableName,
919   DATA_OBJECT_PTR vPtr)
920   {
921    return EnvSetDefglobalValue(GetCurrentEnvironment(),variableName,vPtr);
922   }
923 
SetGlobalsChanged(int value)924 globle void SetGlobalsChanged(
925   int value)
926   {
927    EnvSetGlobalsChanged(GetCurrentEnvironment(),value);
928   }
929 
930 #endif /* ALLOW_ENVIRONMENT_GLOBALS */
931 
932 #endif /* DEFGLOBAL_CONSTRUCT */
933 
934 
935