My Project
 All Classes Files Functions Variables Enumerations Enumerator Friends Macros Pages
script.h
1 #ifndef script_h
2 #define script_h
3 
4 #include <stdarg.h>
5 
6 #include "freelist.h"
7 #include "list.h"
8 #include "hash.h"
9 #include "input.h"
10 #include "output.h"
11 
12 #include <list>
13 #include "gcp/util/common/String.h"
14 
15 /*
16  * Specify the number of buckets per hash table.
17  * This should be a prime number.
18  */
19 #define SC_HASH_SIZE 31
20 
21 /*
22  * Create a type-alias for the primary object of this interface.
23  */
24 typedef struct Script Script; /* see below for definition */
25 
26 /*-----------------------------------------------------------------------
27  * The following functions are required for creating and deleting
28  * a script environment, and compiling and running a script.
29  */
30 
31 /*
32  * Where project-specific datatypes and/or variables allocate non-script
33  * resources that need to be released when the script is discarded and/or
34  * deleted the caller should provide a constructor and destructor function
35  * to create and destroy this data. Any of the data which is associated
36  * with a particular compilation run (eg. with local variables) should
37  * be discarded by clr_fn() when it is called by discard_script().
38  */
39 #define SC_NEW_FN(fn) void *(fn)(Script *sc)
40 #define SC_CLR_FN(fn) int (fn)(Script *sc, void *data)
41 #define SC_DEL_FN(fn) void *(fn)(Script *sc, void *data)
42 
43 /*
44  * The following are the script environment constructor and
45  * destructor functions.
46  */
47 Script *new_Script(void *project, SC_NEW_FN(*new_fn), SC_CLR_FN(*clr_fn),
48  SC_DEL_FN(*del_fn), HashTable *signals);
49 Script *del_Script(Script *sc);
50 
51 /*
52  * The following functions can be used to compile a new script
53  * or prematurely discard an old one. Note that compile_script()
54  * calls discard_script().
55  */
56 int compile_script(Script *sc, char *name, InputStream *argstr,
57  InputStream *stream, int restricted, bool interactive);
58 int rewind_script(Script *sc);
59 int discard_script(Script *sc);
60 char *script_name(Script *sc);
61 int output_script_spec(OutputStream *out, Script *sc);
62 
63 /*
64  * Compile, run and discard an interactive command.
65  */
66 int run_interactive_command(Script *sc, OutputStream *log, char *command);
67 
68 /*
69  * Test wether a script is currently polling in an until statement.
70  */
71 int script_is_polling(Script *sc);
72 
73 /* Scripts are executed one leaf-statement at a time. After a
74  * successful call to compile_script(), one leaf-statement will be
75  * executed each time that you call step_script(). This function will
76  * return SCRIPT_ACTIVE if no error occured and there are further
77  * statements to be run, SCRIPT_ERROR if an error occured, or
78  * SCRIPT_END when the last statement has been executed. After an
79  * error, or on reaching the end of the script, you should call either
80  * discard_script() to allow a new script to be compiled, or
81  * rewind_script() to stage the same script to be run again. A running
82  * script can also be restarted at any time by calling rewind_script()
83  * before the next call to step_script().
84  */
85 typedef enum {
86  SCRIPT_EMPTY, /* No script has been compiled yet */
87  SCRIPT_ACTIVE, /* The next statement of the script can be run */
88  SCRIPT_ERROR, /* An error occured */
89  SCRIPT_EXITING,/* An exit handler is being executed */
90  SCRIPT_END /* There are no more statements to be executed */
91 } ScriptState;
92 
93 ScriptState step_script(Script *sc, OutputStream *log);
94 ScriptState exit_script(Script *sc, char *reason);
95 ScriptState script_state(Script *sc);
96 
97 /*-----------------------------------------------------------------------
98  * The following section describes the contents of a script environment.
99  *
100  * Create type aliases for free-lists of script objects and
101  * provide constructor wrappers around new_FreeList() to request
102  * objects of the required sizes.
103  */
104 typedef FreeList CommandMem;
105 CommandMem *new_CommandMem(Script *sc);
106 
107 typedef FreeList FunctionMem;
108 FunctionMem *new_FunctionMem(Script *sc);
109 
110 typedef FreeList ScOperatorMem;
111 ScOperatorMem *new_ScOperatorMem(Script *sc);
112 
113 typedef FreeList DataTypeMem;
114 DataTypeMem *new_DataTypeMem(Script *sc);
115 
116 typedef FreeList StatementMem;
117 StatementMem *new_StatementMem(Script *sc);
118 
119 typedef FreeList ExprMem;
120 ExprMem *new_ExprMem(Script *sc);
121 
122 typedef FreeList ExprOperMem;
123 ExprOperMem *new_ExprOperMem(Script *sc);
124 
125 typedef FreeList LoopStateMem;
126 LoopStateMem *new_LoopStateMem(Script *sc);
127 
128 typedef FreeList TypeSpecMem;
129 TypeSpecMem *new_TypeSpecMem(Script *sc);
130 
131 typedef FreeList ExeFrameMem;
132 ExeFrameMem *new_ExeFrameMem(Script *sc);
133 
134 typedef FreeList ListVariableMem;
135 ListVariableMem *new_ListVariableMem(Script *sc);
136 
137 /*
138  * Create type aliases for lists of script-objects.
139  */
140 typedef List VariableList;
141 typedef List TypeSpecList;
142 typedef List StatementList;
143 typedef List ScopeStack;
144 typedef List CompStack;
145 typedef List ExprOperList;
146 typedef List LoopStateList;
147 typedef List ModifierList;
148 
149 /*
150  * Create type aliases for script objects.
151  */
152 typedef struct Command Command; /* see below for definition */
153 typedef struct Function Function; /* see below for definition */
154 typedef struct ScOperator ScOperator; /* see below for definition */
155 typedef struct DataType DataType; /* see below for definition */
156 typedef struct Variable Variable; /* see below for definition */
157 typedef struct Statement Statement; /* see statement.c for definition */
158 typedef struct Expr Expr; /* see expr.c for definition */
159 typedef struct ExprOper ExprOper; /* see expr.c for definition */
160 typedef struct LoopState LoopState; /* see statement.c for definition */
161 typedef struct TypeSpec TypeSpec; /* see below for definition */
162 typedef struct ScriptObj ScriptObj; /* see below for definition */
163 typedef struct ExeFrame ExeFrame; /* See below for definition */
164 typedef struct StringPool StringPool;/* See stringpool.c for implementation */
165 
166 /*
167  * All of the objects that are both allocated from free-lists and
168  * defined in this file, have a member of the following type as their
169  * first member. A new object of any of the provided types must be
170  * allocated via new_ScriptObject(), which will use the specified
171  * freelist to allocate the object and also record it in the header
172  * of the object. If the object is allocated while a script is active
173  * it will be pushed onto a stack of temporary objects that are to
174  * be returned to their respective free-lists after the active
175  * script is completed. Otherwise the object is treated as a permanent
176  * builtin and thus will not be reclaimed until its freelist is deleted.
177  */
178 struct ScriptObj {
179  ScriptObj *next; /* The next in a list of temporary objects */
180  FreeList *fl; /* The free-list from which the object was allocated */
181 };
182 
183 void *new_ScriptObject(Script *sc, FreeList *fl, size_t node_size);
184 
185 /*
186  * To acquire a freelist for a Script object, call this function
187  * in place of new_FreeList(). If a compatible freelist has already been
188  * allocated via a previous call to this function, then that freelist
189  * is returned. Otherwise it creates a new freelist and adds it to the
190  * list of allocated freelists in Script::memory.freelists.
191  */
192 FreeList *new_ScriptFreeList(Script *sc, size_t node_size);
193 
194 /*
195  * Lists that are allocated as part of a script object must be allocated
196  * via new_ScriptList(), not directly through new_List(). If a script
197  * is active, the new list will be added to the list of temporary lists
198  * that are to be returned to the free-list when the current script
199  * completes.
200  */
201 List *new_ScriptList(Script *sc);
202 
203 enum DataTypeId {
204  DT_UNK,
205  DT_LIST,
206  DT_UINT,
207  DT_SET,
208  DT_CHOICE,
209  DT_BOOL,
210  DT_INT,
211  DT_DOUBLE,
212  DT_SCRIPT,
213  DT_SEXAGESIMAL,
214  DT_STRING,
215  DT_SYMBOL
216 };
217 
218 struct CmdArg {
219  std::string dataTypeName_;
220  std::string varName_;
221  bool isOptional_;
222 
223  CmdArg() {}
224 
225  CmdArg(std::string dataTypeName, std::string varName, bool isOptional) {
226  dataTypeName_ = dataTypeName;
227  varName_ = varName;
228  isOptional_ = isOptional;
229  }
230 
231  CmdArg(CmdArg& arg) {
232  *this = arg;
233  }
234 
235  CmdArg(const CmdArg& arg) {
236  *this = arg;
237  }
238 
239  void operator=(const CmdArg& arg) {
240  *this = (CmdArg&)arg;
241  }
242 
243  void operator=(CmdArg& arg) {
244  dataTypeName_ = arg.dataTypeName_;
245  varName_ = arg.varName_;
246  isOptional_ = arg.isOptional_;
247  }
248 };
249 
251  gcp::util::String name_;
252  DataTypeId id_;
253  void* context_;
254 
255  ScriptDataType() {}
256 
257  ScriptDataType(std::string name, DataTypeId id, void* context=0) {
258  name_ = name;
259  id_ = id;
260  context_ = context;
261  }
262 
263  ScriptDataType(const ScriptDataType& dataType) {
264  name_ = dataType.name_;
265  id_ = dataType.id_;
266  context_ = dataType.context_;
267  }
268 
269  bool operator<(ScriptDataType& cmd) {
270  return name_ < cmd.name_;
271  }
272 
273  bool operator==(ScriptDataType& dataType) {
274  return name_ == dataType.name_;
275  }
276 };
277 
278 enum {
279  SCR_COMMAND,
280  SCR_FUNCTION,
281  SCR_SYMBOL
282 };
283 
284 struct ScriptCmd {
285  std::string declaration_;
286  std::string description_;
287  gcp::util::String name_;
288  std::list<CmdArg> argList_;
289  CmdArg retType_;
290  unsigned type_;
291 
292  ScriptCmd() {}
293 
294  ScriptCmd(std::string name) {
295  name_ = name;
296  }
297 
298  ScriptCmd(const ScriptCmd& cmd) {
299  name_ = cmd.name_;
300  declaration_ = cmd.declaration_;
301  description_ = cmd.description_;
302  type_ = cmd.type_;
303  retType_ = cmd.retType_;
304 
305  argList_.clear();
306  for(std::list<CmdArg>::const_iterator iArg=cmd.argList_.begin(); iArg != cmd.argList_.end(); iArg++)
307  argList_.insert(argList_.end(), *iArg);
308  }
309 
310  bool operator<(ScriptCmd& cmd) {
311  return name_ < cmd.name_;
312  }
313 };
314 
315 struct Script {
316  void *project; /* Optional project-specific environment data */
317  void *data; /* Script-specific project data */
318  SC_CLR_FN(*clr_fn); /* The discard function for 'data' if needed */
319  SC_DEL_FN(*del_fn); /* The destructor for 'data' if needed */
320  InputStream *input; /* An unopened generic input-stream */
321  OutputStream *output; /* A stream wrapper around lprintf(stdout) */
322  char *host; /* The name of the host computer */
323 /*
324  * All script objects except strings are allocated from the following freelists.
325  */
326  struct {
327  HashMemory *hashtable; /* Memory for HashTable objects */
328  ListMemory *list; /* Memory for allocating lists */
329  CommandMem *command; /* Memory for Command objects */
330  FunctionMem *function; /* Memory for Function objects */
331  ScOperatorMem *scoperator; /* Memory for ScOperator objects */
332  DataTypeMem *datatype; /* Memory for Datatype objects */
333  StatementMem *statement; /* Memory for Statement objects */
334  LoopStateMem *loopstate; /* Memory for LoopState objects */
335  ExprMem *expr; /* Memory for Expr objects */
336  ExprOperMem *exproper; /* Memory for ExprOper objects */
337  TypeSpecMem *typespec; /* Memory for TypeSpec objects */
338  ExeFrameMem *exeframe; /* Memory for ExeFrame objects */
339  ListVariableMem *list_var;/* Memory for list variables */
340  List *freelists; /* A list of freelists of different sizes */
341  } memory;
342 /*
343  * Builtin symbols are kept in a separate scope from compiled programs.
344  * Similarly, to allow fast garbage collection of strings used by
345  * temporary scripts strings for builtin objects are allocated
346  * from a separate pool of strings than strings for ephemeral script
347  * objects.
348  */
349  struct {
350  HashTable *symbols; /* Symbol table of builtin objects */
351  StringPool *strings; /* A pool for allocating builtin strings */
352  DataType *boolvar_dt; /* An alias of the Boolean datatype object */
353  DataType *string_dt; /* An alias of the String datatype object */
354  DataType *symbol_dt; /* An alias of the Symbol datatype object */
355  DataType *double_dt; /* A generic floating point datatype */
356  DataType *integer_dt; /* A generic integral datatype */
357  DataType *sexagesimal_dt;/* A generic floating point datatype, input */
358  /* and output in sexagesimal notation. */
359  DataType *input_file_dt; /* A generic readable file datatype */
360  DataType *signal_dt; /* The Signal datatype */
361  } builtin;
362 /*
363  * The following container contains transitory information associated
364  * with the current user script.
365  */
366  struct {
367  char *name; /* The name of the script */
368  VariableList *args; /* The argument list of the script */
369  struct {
370  StatementList *stmts; /* Statements to be run on exit */
371  Variable *reason; /* The argument of the cleanup handler */
372  } cleanup;
373  ScriptState state; /* The executable status of the script */
374  ScopeStack *scopes; /* A compile-time stack of local symbol scopes */
375  CompStack *comp_stack; /* A compile-time stack of nested statements */
376  ExeFrame *exe_stack; /* The stack of currently executing statements */
377  StatementList *stmts; /* The top-level statements of the program */
378  HashTable *signals; /* A symbol table of currently known signals */
379  List *catch_list; /* The list of running catch statements */
380 /*
381  * The following structure contains lists of all temporary objects that
382  * are allocated to the current script. When the script is complete
383  * the listed objects will be returned to their respective freelists.
384  */
385  struct {
386  List *lists; /* The list of lists to be deleted */
387  ScriptObj *objects; /* The list of script objects to be deleted */
388  StringPool *strings; /* The pool of temporary strings */
389  } temporary;
390  } script;
391 
392  std::list<ScriptCmd>* commands_;
393  std::list<ScriptCmd>* functions_;
394  std::list<ScriptCmd>* symbols_;
395 
396  std::list<ScriptDataType>* dataTypes_;
397  bool interactive_; // True if this is an interactive script
398 
399  void insert(const ScriptDataType& dataType) {
400  if(!exists(dataType.name_))
401  dataTypes_->insert(dataTypes_->end(), dataType);
402  }
403 
404  bool exists(const gcp::util::String& name) {
405  for(std::list<ScriptDataType>::iterator iDat=dataTypes_->begin();
406  iDat != dataTypes_->end(); iDat++)
407  if((*iDat).name_ == name)
408  return true;
409 
410  return false;
411  }
412 
413  // Insert an argument into the passed command. If the argument data
414  // type doesn't already exist, then create an entry for it in our
415  // list of data types
416 
417  void insert(ScriptCmd* cmd, const CmdArg& cmdArg) {
418  if(!exists(cmdArg.dataTypeName_))
419  dataTypes_->insert(dataTypes_->end(),
420  ScriptDataType(cmdArg.dataTypeName_, DT_UNK));
421 
422  cmd->argList_.insert(cmd->argList_.end(), cmdArg);
423  }
424 
425 };
426 
427 /*
428  * Provide accessor functions for builtin types.
429  */
430 DataType *sc_Boolean_dt(Script *sc);
431 DataType *sc_String_dt(Script *sc);
432 DataType *sc_Symbol_dt(Script *sc);
433 DataType *sc_Double_dt(Script *sc);
434 DataType *sc_Integer_dt(Script *sc);
435 DataType *sc_Sexagesimal_dt(Script *sc);
436 DataType *sc_InputFile_dt(Script *sc);
437 DataType *sc_Signal_dt(Script *sc);
438 
439 /*-----------------------------------------------------------------------
440  * The following section is concerned with compilation of statements
441  * and expressions.
442  */
443 
444 /*
445  * The different types of symbols in a given symbol table are
446  * distinguished by the following enumerators.
447  */
448 typedef enum {
449  SYM_VARIABLE, /* Symbol::data contains a pointer to a Variable */
450  SYM_FUNCTION, /* Symbol::data contains a pointer to a Function */
451  SYM_COMMAND, /* Symbol::data contains a pointer to a Command */
452  SYM_DATATYPE, /* Symbol::data contains a pointer to a DataType */
453  SYM_FUNCTION_KEYWORD, /* The "function" reserved word */
454  SYM_COMMAND_KEYWORD, /* The "command" reserved word */
455  SYM_LISTOF_KEYWORD, /* The "listof" reserved word */
456  SYM_GROUP_KEYWORD, /* The "group" reserved word */
457  SYM_FOREACH_KEYWORD, /* The "foreach" reserved word */
458  SYM_DO_KEYWORD, /* The "do" reserved word */
459  SYM_UNTIL_KEYWORD, /* The "until" reserved word */
460  SYM_WHILE_KEYWORD, /* The "while" reserved word */
461  SYM_IF_KEYWORD, /* The "if" reserved word */
462  SYM_IFHOST_KEYWORD, /* The "ifhost" command */
463  SYM_PRINT_KEYWORD, /* The "print" reserved word */
464  SYM_LOG_KEYWORD, /* The "log" reserved word */
465  SYM_BREAK_KEYWORD, /* The "break" command */
466  SYM_NEXT_KEYWORD, /* The "next" command */
467  SYM_EXIT_KEYWORD, /* The "exit" command */
468  SYM_IMPORT_KEYWORD, /* The "import" command */
469  SYM_CLEANUP_KEYWORD, /* The "cleanup" command */
470  SYM_RETURN_KEYWORD, /* The "return" command */
471  SYM_CATCH_KEYWORD /* The "catch" command */
472 } SymbolType;
473 
474 /*
475  * Parse a brace-enclosed or non-brace-enclosed list of statements.
476  */
477 StatementList *parse_StatementList(Script *sc, InputStream *stream, int braces);
478 StatementList *parse_RestrictedStatementList(Script *sc, InputStream *stream);
479 
480 /*
481  * Parse a statement from an input stream. In interactive mode restrict
482  * to simple builtin statements.
483  */
484 Statement *parse_Statement(Script *sc, InputStream *stream, int interactive);
485 
486 /*
487  * The following type is used to record the declaration of a given
488  * variable.
489  */
490 struct TypeSpec {
491  ScriptObj header; /* The generic script-object header */
492  char *name; /* The name of the variable or function */
493  DataType *dt; /* The type-declaration of the variable */
494  int is_list; /* True if the variable is a list of type 'dt' */
495 };
496 
497 TypeSpec *new_TypeSpec(Script *sc, char *name, DataType *dt, int is_list);
498 TypeSpec *append_TypeSpec(Script *sc, TypeSpecList *tl, TypeSpec *ts);
499 TypeSpec *parse_TypeSpec(Script *sc, InputStream *stream, Symbol *symbol);
500 TypeSpecList *new_TypeSpecList(Script *sc);
501 
502 /*
503  * The body of a user-defined command is a list of statements.
504  */
505 typedef struct {
506  StatementList *stmts; /* The statements that implement the procedure */
507 } UserCmd;
508 
509 /*
510  * Command modifier arguments are listed in containers of the following
511  * type.
512  */
513 typedef struct {
514  ScriptObj header; /* The generic script-object header */
515  char *name; /* The name used to refer to the modifier */
516  Variable *arg; /* The argument that records the modifier */
517 } Modifier;
518 
519 /*
520  * Builtin commands use a C function to implement the procedure.
521  */
522 
523 #define CMD_FN(fn) int (fn)(Script *sc, VariableList *args)
524 
525 typedef struct {
526  CMD_FN(*cmd_fn); /* The C function that implements the script command */
527 } BuiltinCmd;
528 
529 struct Command {
530  ScriptObj header; /* The generic script-object header */
531  char *name; /* The name of the command */
532  ModifierList *mods; /* The list of command modifiers, or NULL if */
533  /* there aren't any. */
534  VariableList *args; /* The list of command arguments order as */
535  /* boolean modifiers, mandatory arguments, */
536  /* optional arguments. */
537  unsigned narg; /* The number of command arguments */
538  ListNode *opt; /* The first of the trailing list of optional */
539  /* arguments in 'args' (NULL if none are optional). */
540  int is_builtin; /* True if the function is implemented in C */
541  union {
542  BuiltinCmd builtin;/* A builtin command implemented in C */
543  UserCmd user; /* A user-defined command */
544  } body;
545 };
546 
547 Command *add_UserCommand(Script *sc, InputStream *stream);
548 Command *add_BuiltinCommand(Script *sc, char *declaration, CMD_FN(*cmd_fn), std::string description);
549 Command *add_BuiltinCommand(Script *sc, char *declaration, CMD_FN(*cmd_fn));
550 int add_UserAlias(Script *sc, char* command, char* alias);
551 
552 /*
553  * The body of a user-defined function is a single expression which
554  * evaluates to the function return value.
555  * No statements are allowed.
556  */
557 typedef struct {
558  Expr *expr; /* The expression that implements the function */
559 } UserFn;
560 
561 /*
562  * Builtin functions use a C function to implement the procedure, and an
563  * optional loop-state function that allows loop-specific data to be
564  * initialized at the start of loops which use the procedure, and
565  * stepped in parallel with the loop. The FUN_FN() state member is NULL
566  * for normal functions. For loop-state functions the state member is
567  * used to pass the current state of the value that is initialized and
568  * stepped by loop_fn(). Examples of loop-state functions include:
569  *
570  * A boolean elapsed(time) function that returns true when the enclosing
571  * loop has been running for a given length of time.
572  *
573  * A boolean repeated(n) function that returns true after the nth iteration
574  * of the loop, or a loop_count() function that returns the current iteration
575  * number.
576  */
577 
578 #define FUNC_FN(fn) int (fn)(Script *sc, VariableList *args, Variable *result, \
579  Variable *state)
580 typedef enum {
581  LOOP_ENTER, /* Initialize a loop-state object on entry to loop */
582  LOOP_INCR, /* Step the loop-state object on new iteration of loop */
583  LOOP_EXIT /* Cleanup loop-state object on loop exit */
584 } LoopOper;
585 
586 #define LOOP_FN(fn) void (fn)(Script *sc, Variable *state, LoopOper oper)
587 
588 typedef struct {
589  FUNC_FN(*func_fn); /* The C function that implements the script function */
590  LOOP_FN(*loop_fn); /* An optional loop-iteration function */
591  TypeSpec *loop_type; /* The loop-state datatype (NULL if loop_fn==0) */
592 } BuiltinFn;
593 
594 /*
595  * This is used by expr::parse_function_call() to get the state
596  * objects associated with loop-state functions and their nearest enclosing
597  * loops.
598  */
599 Variable *get_loop_data(Script *sc, InputStream *stream, Function *func);
600 
601 struct Function {
602  ScriptObj header; /* The generic script-object header */
603  TypeSpec *return_type; /* The return type of the function */
604  VariableList *args; /* The list of function arguments */
605  unsigned narg; /* The number of function arguments */
606  ListNode *opt; /* The first of the trailing list of optional */
607  /* arguments in 'args' (NULL if none are optional). */
608  int is_builtin; /* True if the function is implemented in C */
609  union {
610  BuiltinFn builtin; /* A builtin function implemented in C */
611  UserFn user; /* A user-defined function */
612  } body;
613 };
614 
615 Function *add_UserFunction(Script *sc, InputStream *stream);
616 Function *add_BuiltinFunction(Script *sc, char *declaration, FUNC_FN(*func_fn), std::string description);
617 Function *add_BuiltinFunction(Script *sc, char *declaration, FUNC_FN(*func_fn));
618 Function *add_LoopStateFunction(Script *sc, char *declaration,
619  FUNC_FN(*func_fn), LOOP_FN(*loop_fn),
620  char *datatype);
621 
622 /*
623  * ScOperators are implemented via C functions of the following form.
624  */
625 #define OPER_FN(fn) int (fn)(Script *sc, VariableList *args, Variable *result)
626 struct ScOperator {
627  ScriptObj header; /* The generic script-object header */
628  OPER_FN(*oper_fn); /* The C function that implements the scoperator */
629  TypeSpec *return_type; /* The return type of the scoperator */
630  int narg; /* The number of arguments expected by the scoperator*/
631 };
632 ScOperator *new_ScOperator(Script *sc, DataType *return_dt, int narg,
633  OPER_FN(*oper_fn));
634 
635 
636 /*
637  * Define the method functions that support a given datatype.
638  */
639 
640 /*.......................................................................
641  * The following method is called to parse an expression of its datatype
642  * from an input stream.
643  *
644  * If the datatype doesn't support any expressions then this
645  * method can be omitted. To read the operands of the expression such
646  * methods should call parse_operand(). To parse scoperators they should
647  * use InputStream functions defined in input.h to read from 'stream', and
648  * add_OpFnOper() to push scoperator functions onto the expression 'e'.
649  *
650  * On error this function should return non-zero (eg. 1) and leave an
651  * error message in the input stream error buffer, via a call to
652  * input_error().
653  */
654 #define DT_PARSE(fn) int (fn)(Script *sc, DataType *dt, \
655  InputStream *stream, Expr *e)
656 
657 /*.......................................................................
658  * The following mandatory method is called to parse a constant of its
659  * datatype from an input stream.
660  *
661  * It should use functions from input.h to parse the constant, then
662  * call new_Variable() to allocate a variable for the constant,
663  * append an instruction to load that variable to the expression 'e',
664  * and initialize the variable with the constant value that was read.
665  *
666  * On error this function should return non-zero (eg. 1) and leave an
667  * error message in the input stream error buffer, via a call to
668  * input_error().
669  */
670 #define DT_CONST(fn) int (fn)(Script *sc, DataType *dt, \
671  InputStream *stream, Expr *e)
672 
673 /*.......................................................................
674  * The following method is called to print the value of a variable of its
675  * datatype to a given output stream. It should return non-zero on error.
676  */
677 #define DT_PRINT(fn) int (fn)(Script *sc, OutputStream *output, Variable *var)
678 
679 /*.......................................................................
680  * The following method is called to check a value parsed by a DT_CONST()
681  * method. It is kept separate from the DT_CONST() method so as to cater
682  * for datatypes that differ only in the legal ranges of values that they
683  * support. For other types, where the value is validated by the DT_CONST()
684  * method, this method can be omitted (pass 0 to new_DataType()).
685  */
686 #define DT_CHECK(fn) int (fn)(Script *sc, Variable *var, InputStream *stream)
687 
688 /*.......................................................................
689  * The following optional method is used by the 'do' command to set the
690  * current value of a do-loop variable of the associated datatype.
691  * At the start of a new loop that has a variable of the datatype that
692  * this function is registered to, the function will be called with
693  * value=NULL. This indicates that the function should compute
694  * the number of steps involved in the do loop and return it. The step
695  * should be computed as:
696  *
697  * nstep = floor((last - first) / step) + 1
698  *
699  * If the returned value is less than 2, no iteration is possible, so
700  * the do-statement will simply run the body of the loop once with
701  * multiplier=0. If first==last or 'step' goes in the opposite
702  * direction to first..last, simply return 0.
703  *
704  * The function will be called nstep times, with 'multiplier'
705  * set to 0..nstep-1. If nstep < 1, the function will be called
706  * once with multiplier=0. The function should assign the following
707  * value to 'value':
708  *
709  * first + step * multiplier
710  */
711 #define DT_ITER(fn) int (fn)(Script *sc, Variable *first, Variable *last, \
712  Variable *step, int multiplier, Variable *value)
713 
714 /*
715  * This is a do-loop iterator function suitable for use with datatypes
716  * in which both the datatype itself, and its incrementing datatype,
717  * are implemented as DoubleVariable's. Possible incrementing datatypes
718  * include the builtin datatypes returned by sc_Double_dt(sc) and
719  * sc_Sexagesimal_dt(sc).
720  */
721 DT_ITER(sc_iterate_double);
722 
723 /*
724  * This is a do-loop iterator function suitable for use with datatypes
725  * in which both the datatype itself, and its incrementing datatype,
726  * are implemented as IntVariable's. Possible incrementing datatypes
727  * include the builtin datatype returned by sc_Integer_dt(sc).
728  */
729 DT_ITER(sc_iterate_int);
730 
731 /*
732  * This is a do-loop iterator function suitable for use with datatypes
733  * in which the datatype is implemented as a UintVariable and its
734  * incrementing datatype is implemented as a IntVariable. Possible
735  * incrementing datatypes include the builtin datatype returned by
736  * sc_Integer_dt(sc).
737  */
738 DT_ITER(sc_iterate_uint);
739 
740 /*
741  * Group datatypes are the equivalent of C structs or Pascal records.
742  * A pointer to a different object of the following type is recorded in the
743  * context member of the DataType structure. It contains the distinguishing
744  * attributes of each group type.
745  */
746 typedef struct { /* The instance data of a 'group' datatype */
747  ScriptObj header; /* The required garbage collection header */
748  char *name; /* The symbol-name given to the type */
749  TypeSpecList *fields; /* The group-field variable declarations */
750  int nfield; /* The number of group fields */
751 } GroupType;
752 
753 DataType *add_GroupDataType(Script *sc, InputStream *stream);
754 DataType *add_BuiltinGroupDataType(Script *sc, char *declaration);
755 
756 /*
757  * The following type is used to contain one name/value pair of
758  * a 'choice' or 'set' datatype.
759  */
760 struct Enumerator { /* An enumeration name/value pair */
761  char *name; /* The name of the enumerator */
762  unsigned value; /* The value of the enumerator */
763  char* explanation; /* An optional explanation of what this value means */
764 };
765 
766 /*
767  * There is only one boolean datatype.
768  *
769  * Boolean values are stored in BoolVariable variables.
770  */
771 DataType *add_BooleanDataType(Script *sc);
772 
773 /*
774  * Choice datatypes are like C enumerations. They present the user with
775  * a symbolic menu of choices from which the user can pick one entry
776  * at a time.
777  *
778  * Choice values are stored in ChoiceVariable variables.
779  */
780 DataType *add_ChoiceDataType(Script *sc, char *name, Enumerator *choices,
781  int nchoice);
782 
783 /*
784  * Set datatypes allow the user to specify one or more members of a set
785  * of up to 32 symbolic names, via expressions in which members are added
786  * to the set with '+' and removed from the set with '-'. The C values
787  * associated with set members are to be interpretted as bit-masks.
788  * Adding a member to a set is equivalent to a bitwise OR of the member
789  * value with the current bitset. Removing from a set is equivalent to
790  * a bitwise AND of the complement of the member with the current bitset.
791  *
792  * Set values are stored in SetVariable variables.
793  */
794 DataType *add_SetDataType(Script *sc, char *name, int allow_bit_mask,
795  Enumerator *members, unsigned nmember, DT_ITER(*iter_fn), char *incr_name);
796 
797 /*
798  * Create a quoted or optionally unquoted string datatype.
799  * If the 'quoted' argument of add_StringDataType() is true, then
800  * strings that the user enters must be enclosed in quotes.
801  * If the quoted argument is false, then quotes can optionally be omitted,
802  * and the end of the string will be the point at which an unopened
803  * close bracket or quote is seen, or a comma is encountered outside of
804  * parentheses or quotes.
805  */
806 DataType *add_StringDataType(Script *sc, char *name, int quoted,
807  DT_CHECK(*check_fn));
808 
809 /*
810  * Create a keyword datatype. Constants of this datatype are
811  * stored in StringVariable's. A valid keyword is one that
812  * starts with an alphabetic character then continues with
813  * alphanumeric and underscore characters. If you need the
814  * alphabetical characters to be folded to lower case, pass
815  * fold=1, otherwise pass fold=0. After a syntactically
816  * valid keyword has been read, the optional check_fn() is
817  * called to see if the keyword is valid for the particular
818  * datatype.
819  */
820 DataType *add_KeywordDataType(Script *sc, char *name, int fold,
821  DT_CHECK(*check_fn));
822 
823 /*
824  * Create a pathname datatype. Constants of this datatype are
825  * read as literal strings. If the first character is a ~ then
826  * home-directory substitution is performed. Validation of the
827  * pathname should be performed by the caller's check_fn().
828  */
829 DataType *add_PathDataType(Script *sc, char *name, DT_CHECK(*check_fn));
830 
831 /*
832  * There is only one symbol datatype.
833  *
834  * Symbol values are stored in SymbolVariable variables.
835  */
836 DataType *add_SymbolDataType(Script *sc);
837 
838 /*
839  * Provide a way to distinguish between builtin and aggregate types.
840  */
841 typedef enum {
842  DT_GROUP, /* User-defined group datatypes */
843  DT_BUILTIN /* A builtin datatype */
844 } TypeClass;
845 
846 /*
847  * There are two relational scoperators that datatypes can support.
848  * The equality scoperator is mandatory. The greater-than method
849  * is optional. They are implemented by functions of the following
850  * type.
851  *
852  * Input:
853  * va Variable * The first of two variables of the parent dataype.
854  * vb Variable * The second of two variables of the parent dataype.
855  * Output:
856  * return int 0 - The relation was not satisfied.
857  * 1 - The relation was satisfied.
858  */
859 #define DT_RELFN(fn) int (fn)(Variable *va, Variable *vb)
860 
861 /*
862  * Each data-type that is recognized by the interpretter is described by
863  * an object of the following type. Datatypes that are added when
864  * sc->prog is NULL are added to the global scope. Thereafter they
865  * are added to the current local scope.
866  */
867 struct DataType {
868  ScriptObj header; /* The generic script-object header */
869  char *name; /* The name of the datatype */
870  DT_PARSE(*parse_fn); /* A method to parse an expression of the datatype */
871  DT_CONST(*const_fn); /* A method to parse a constant of the datatype */
872  DT_CHECK(*check_fn); /* A method to domain-check a value of the datatype */
873  DT_PRINT(*print_fn); /* A method to print an instance of the datatype */
874  DT_RELFN(*eq_fn); /* A method that returns 1 if a == b, 0 if a != b */
875  DT_RELFN(*gt_fn); /* An optional method that returns 1 if a > b */
876  DT_RELFN(*in_fn); /* An optional method that returns 1 if a contains b */
877  DT_ITER(*iter_fn); /* The optional do-loop iteration function */
878  DataType *incr_dt; /* The incremental datatype to for iter_fn() steps */
879  void *context; /* Type-specific context data */
880  size_t vsize; /* The size of a variable of this datatype */
881  FreeList *vmemory; /* The free-list from which to allocate variables */
882  TypeSpec *list_reg; /* The listof type specifier for registers */
883  TypeSpec *atom_reg; /* The type specifier for registers */
884  Variable *null_atom; /* A null atom variable of this datatype */
885  Variable *null_list; /* A null list variable of this datatype */
886  TypeClass dataclass; /* The dataclass of datatype */
887  DataTypeId id;
888 };
889 
890 DataType *new_DataType(Script *sc, char *name, TypeClass dataclass,
891  void *context, size_t vsize,
892  DT_CHECK(*check_fn), DT_PARSE(*parse_fn),
893  DT_CONST(*const_fn), DT_PRINT(*print_fn),
894  DT_RELFN(*equal_fn), DT_RELFN(*gt_fn), DT_RELFN(*in_fn),
895  DT_ITER(*iter_fn), char *incr_name,
896  DataTypeId id = DT_UNK);
897 
898 /*
899  * Some data-types have well defined syntactic and storage
900  * formats formats but value domains that depend on their
901  * specific usage. Thus the following constructors provide the
902  * parsing and print functions for a set of general datatypes,
903  * but require a domain-checking function to complete the datatype
904  * implementation.
905  */
906 
907 /* Create an unsigned integer datatype (See UintVariable) */
908 
909 DataType *add_UintDataType(Script *sc, char *name, DT_CHECK(*check_fn),
910  DT_ITER(*iter_fn), char *incr_name);
911 
912 /* Create a signed-int datatype (see IntVariable) */
913 
914 DataType *add_IntDataType(Script *sc, char *name, DT_CHECK(*check_fn),
915  DT_ITER(*iter_fn), char *incr_name,
916  int allow_negation);
917 
918 /* Create a double-precision datatype used (see DoubleVariable) */
919 
920 DataType *add_DoubleDataType(Script *sc, char *name, DT_CHECK(*check_fn),
921  DT_ITER(*iter_fn), char *incr_name,
922  int allow_negation);
923 
924 /*
925  * Add a sexagesimal datatype.
926  *
927  * The resulting number is recorded in a DoubleVariable with the units
928  * of the first sexagesimal component. For example if one entered
929  * -12:30:36.0, then the recorded value would be -12.51.
930  */
931 DataType *add_SexagesimalDataType(Script *sc, char *name, DT_CHECK(*check_fn),
932  DT_ITER(*iter_fn), char *incr_name,
933  int allow_negation);
934 
935 DataType *add_Sexagesimal24DataType(Script *sc, char *name, DT_CHECK(*check_fn),
936  DT_ITER(*iter_fn), char *incr_name,
937  int allow_negation);
938 
939 /*
940  * Parse an operand of a given datatype. This is intended for use
941  * by the parse_fn() methods of datatypes.
942  */
943 int parse_operand(Script *sc, DataType *dt, int is_list,
944  InputStream *stream, Expr *e);
945 
946 /*
947  * Parse a variable reference, function call, or cast expression after
948  * encountering a $ scoperator. The type of the resulting expression is
949  * returned. This will be consistent with dt and is_list unless dt==NULL,
950  * or an error occurs. If dt==NULL, then type-checking will be disabled
951  * and it is left to the caller to check the returned type.
952  */
953 TypeSpec *parse_dollar_expr(Script *sc, DataType *dt, int is_list,
954  InputStream *stream, Expr *e);
955 
956 /*
957  * Parse a single argument expression.
958  */
959 int parse_argument(Script *sc, TypeSpec *target, InputStream *stream, Expr *e);
960 
961 /*
962  * Parse the argument list of a function or command.
963  */
964 int parse_procedure_arguments(Script *sc, char *name, int is_func, List *args,
965  ModifierList *mods, ListNode *opts,
966  InputStream *stream, Expr *e);
967 
968 /*
969  * The following enumerates the values associated with individual bits
970  * of a bitwise union of variable usage flags.
971  */
972 typedef enum {
973  VAR_IS_OPT=1, /* The variable is an optional procedure argument. */
974  /* When the parent procedure is active the */
975  /* VAR_IS_NUL flag must be used to determine whether */
976  /* the argument has been given a value. */
977  VAR_IS_NUL=2, /* The variable currently has no value. */
978  VAR_IS_CONST=4, /* The value of the variable is unchangeable */
979  VAR_IS_MODIFIER=8 /* True if the variable is a boolean command modifier */
980 } VarFlags;
981 
982 /*
983  * All script variables have an initial member of the following type.
984  * This contains the description of the variable type and how to
985  * release it once redundant. All functions that operate on variables
986  * take a Variable * argument, including the type-specific method functions
987  * in Variable::type->dt. Where access to a variable's value is needed,
988  * the Variable * pointer should be cast back to the specific variable type.
989  * This will be a ListVariable type if Variable::type->is_list is
990  * non-zero.
991  */
992 struct Variable {
993  ScriptObj header; /* The generic script-object header */
994  TypeSpec *type; /* The declaration of the variable */
995  unsigned flags; /* A bitwise union of VarFlags enumerators */
996 };
997 
998 Variable *new_Variable(Script *sc, TypeSpec *type);
999 Variable *copy_Variable(Variable *dst, Variable *src);
1000 ListNode *append_Variable(Script *sc, VariableList *vl, Variable *var);
1001 int print_variable(Script *sc, OutputStream *output, Variable *var);
1002 int get_Arguments(VariableList *vl, ...);
1003 int print_ArgumentList(Script *sc, OutputStream *stream, int expand,
1004  VariableList *args);
1005 Variable *add_BuiltinVariable(Script *sc, char *declaration);
1006 
1007 VariableList *new_VariableList(Script *sc);
1008 
1009 /*
1010  * In builtin procedures that take optional arguments, the following
1011  * macro should be applied to each optional argument variable to determine
1012  * whether it has been given a value. The value of the variable should be
1013  * ignored if the macro returns zero.
1014  */
1015 #define OPTION_HAS_VALUE(arg) (~(arg)->flags & VAR_IS_NUL)
1016 
1017 /*
1018  * Describe canned variable types.
1019  */
1020 typedef struct { /* A variable that contains a list of variables */
1021  Variable v; /* Generic variable members */
1022  VariableList *list; /* A list of variables of type v.type->dt */
1023 } ListVariable;
1024 
1025 #define LIST_VARIABLE(v) ((ListVariable *)(v))
1026 
1027 typedef struct { /* An unsigned integer datatype */
1028  Variable v; /* Generic variable members */
1029  unsigned uint; /* The value of the variable */
1030 } UintVariable;
1031 
1032 #define UINT_VARIABLE(v) ((UintVariable *)(v))
1033 
1034 DT_RELFN(sc_equal_uint); /* See if two UintVariable's have the same value */
1035 DT_RELFN(sc_gt_uint); /* See if one UintVariable value is greater */
1036  /* than another. */
1037 
1038 typedef struct { /* A set variable */
1039  Variable v; /* Generic variable members */
1040  unsigned set; /* The bit-mask value of the variable */
1041 } SetVariable;
1042 
1043 #define SET_VARIABLE(v) ((SetVariable *)(v))
1044 
1045 typedef struct { /* A enumerated choice variable */
1046  Variable v; /* Generic variable members */
1047  unsigned choice; /* The enumerated value of the choice */
1048 } ChoiceVariable;
1049 
1050 #define CHOICE_VARIABLE(v) ((ChoiceVariable *)(v))
1051 
1052 typedef struct { /* A boolean variable */
1053  Variable v; /* Generic variable members */
1054  unsigned boolvar; /* The boolean value of the variable. Logical */
1055  /* true is represented by a non-zero value. */
1056 } BoolVariable;
1057 
1058 #define BOOL_VARIABLE(v) ((BoolVariable *)(v))
1059 
1060 typedef struct { /* A signed integer variable */
1061  Variable v; /* Generic variable members */
1062  int i; /* The integer value of the variable */
1063 } IntVariable;
1064 
1065 #define INT_VARIABLE(v) ((IntVariable *)(v))
1066 
1067 DT_RELFN(sc_equal_int); /* See if two IntVariable's have the same value */
1068 DT_RELFN(sc_gt_int); /* See if one IntVariable value is greater than */
1069  /* another. */
1070 
1071 typedef struct { /* A double-precision floating point variable */
1072  Variable v; /* Generic variable members */
1073  double d; /* The value of the variable */
1074 } DoubleVariable;
1075 
1076 #define DOUBLE_VARIABLE(v) ((DoubleVariable *)(v))
1077 
1078 DT_RELFN(sc_equal_double); /* See if two DoubleVariable's have the same value */
1079 DT_RELFN(sc_gt_double); /* See if one DoubleVariable value is greater */
1080  /* than another. */
1081 
1082 typedef struct { /* A string-precision floating point variable */
1083  Variable v; /* Generic variable members */
1084  char *string; /* An immutable string allocated from the string */
1085  /* pool of the script */
1086 } StringVariable;
1087 
1088 #define STRING_VARIABLE(v) ((StringVariable *)(v))
1089 
1090 DT_RELFN(sc_equal_string); /* See if two StringVariable's have equal values */
1091 DT_RELFN(sc_in_string); /* See if one StringVariable value is a substring */
1092  /* of another StringVariable value. */
1093 
1094 typedef struct { /* A script symbol */
1095  Variable v; /* Generic variable members */
1096  SymbolType type; /* The type of symbol refered to by the variable */
1097  union {
1098  Variable *var; /* The variable refered to if type==SYM_VARIABLE */
1099  Function *func; /* The function refered to if type==SYM_FUNCTION */
1100  Command *cmd; /* The command refered to if type==SYM_COMMAND */
1101  DataType *dt; /* The datatype refered to if type==SYM_DATATYPE */
1102  char *keyword; /* The name of a keyword */
1103  } data;
1104 } SymbolVariable;
1105 
1106 #define SYMBOL_VARIABLE(v) ((SymbolVariable *)(v))
1107 
1108 /*-----------------------------------------------------------------------
1109  * The Signal datatype is used to specify a signal to be sent or
1110  * received.
1111  *
1112  * It is stored in a SignalVariable and parsed as a lowercase keyword.
1113  */
1114 typedef struct {
1115  Variable v; /* The base-dataclass members of the variable (see script.h) */
1116  Symbol *sym; /* The symbol-table entry of the signal */
1117 } SignalVariable;
1118 
1119 #define SIGNAL_VARIABLE(v) ((SignalVariable *)(v))
1120 
1121 DataType *add_SignalDataType(Script *sc, char *name);
1122 
1123 /* Expr objects contain compiled expressions (see expr.c) */
1124 
1125 Expr *new_Expr(Script *sc);
1126 
1127 /* An ExprOper object contains one instruction of an expression */
1128 
1129 ExprOper *add_LoadOper(Script *sc, Expr *e, Variable *var);
1130 ExprOper *add_FuncOper(Script *sc, Expr *e, Function *func, Variable *state);
1131 ExprOper *add_ListOper(Script *sc, Expr *e, DataType *dt, unsigned n);
1132 ExprOper *add_GroupOper(Script *sc, Expr *e, DataType *dt);
1133 ExprOper *add_FieldOper(Script *sc, Expr *e, unsigned field);
1134 ExprOper *add_CloneOper(Script *sc, Expr *e, TypeSpec *type);
1135 ExprOper *add_OpFnOper(Script *sc, Expr *e, ScOperator *oper);
1136 ExprOper *add_SkipOper(Script *sc, Expr *e);
1137 ExprOper *add_StoreOper(Script *sc, Expr *e, Variable *var);
1138 ExprOper *add_UnsetOper(Script *sc, Expr *e, Variable *var);
1139 ExprOper *add_SetBoolOper(Script *sc, Expr *e, Variable *var, int state);
1140 ExprOper *add_SetStringOper(Script *sc, Expr *e, Variable *var, char *string);
1141 
1142 /*
1143  * The following two functions are provided for parsing functions that
1144  * need to ensure that an argument doesn't alias a user variable.
1145  * Before parsing the argument, get_ExprEnd() is called to record the
1146  * current end of the expression. Then immediately after parsing the
1147  * argument, remove_alias() is called, along with the position previously
1148  * returned by get_ExprEnd(). remove_alias() checks to see if the
1149  * expression that follows 'old_end' is a variable alias, and if so it
1150  * appends a copy-variable instruction to the instruction list.
1151  */
1152 ListNode *get_ExprEnd(Expr *e);
1153 int remove_alias(Script *sc, Expr *e, ListNode *old_end);
1154 
1155 /*
1156  * Evaluate an expression.
1157  */
1158 int exe_Expr(Script *sc, Expr *expr);
1159 
1160 /*
1161  * Pop a given number of arguments from the expression-evaluation stack and
1162  * return them as an argument list.
1163  */
1164 VariableList *pop_ExprStackArgs(Script *sc, Expr *expr, int narg);
1165 
1166 /*
1167  * Pop a single value from the top of the expression-evaluation stack.
1168  */
1169 Variable *pop_ExprStack(Script *sc, Expr *expr);
1170 
1171 /*
1172  * Allocate a string from the appropriate string pool.
1173  */
1174 char *new_ScriptString(Script *sc, char *string);
1175 
1176 /*
1177  * During compilation the symbol-tables of nested scopes will be
1178  * kept as a list of hash-tables, organized as a stack.
1179  */
1180 int push_Scope(Script *sc);
1181 int pop_Scope(Script *sc);
1182 
1183 /*
1184  * During compilation nested statements are pushed onto a stack.
1185  * This is then used when parsing break, next and loop-state functions.
1186  */
1187 Statement *push_CompStatement(Script *sc, Statement *stmt);
1188 Statement *pop_CompStatement(Script *sc);
1189 
1190 /*
1191  * Add a symbol to the innermost lexical scope.
1192  */
1193 Symbol *add_ScriptSymbol(Script *sc, char *name, SymbolType code, void *data, bool isAlias=false);
1194 Symbol *add_ScriptSymbol(Script *sc, char *name, SymbolType code, std::string description);
1195 
1196 /*
1197  * Work back from the innermost scope to locate a named symbol.
1198  * Note that the stream argument is optional and only used for
1199  * error reporting.
1200  */
1201 Symbol *find_ScriptSymbol(Script *sc, InputStream *stream, char *name, bool printError=true);
1202 
1203 /*
1204  * Attempt to find a datatype by name.
1205  */
1206 DataType *find_DataType(Script *sc, InputStream *stream, char *name);
1207 
1208 /*
1209  * Executing statements or lists of statements are recorded on a stack
1210  * of ExeFrame objects. Each frame records the current statement being
1211  * executed, its list node if it is part of a statement list, and
1212  * the parent execution frame that invoked it.
1213  */
1214 ExeFrame *push_ExeFrame(Script *sc, Statement *stmt, ListNode *next);
1215 Statement *pop_ExeFrame(Script *sc);
1216 
1217 /*
1218  * String pool methods.
1219  */
1220 StringPool *new_StringPool(void);
1221 StringPool *del_StringPool(StringPool *sp);
1222 char *new_StringPool_string(StringPool *sp, char *string);
1223 int clr_StringPool(StringPool *sp);
1224 
1225 /*
1226  * Script signaling functions.
1227  */
1228 int add_script_signal(Script *sc, char *name);
1229 Symbol *lookup_script_signal(Script *sc, char *name);
1230 int signal_script(Script *sc, Symbol *sig);
1231 int clear_script_signal(Symbol *sig);
1232 int reset_script_signal(Symbol *sig);
1233 
1234 /*
1235  * The following function inspects all enclosing catch statements, looking
1236  * for catch clauses that have become true. If such a statement is found,
1237  * the current statement is cancelled, and the execution stack is unwound
1238  * to that statement.
1239  */
1240 typedef enum {
1241  CAUGHT_EVENT, /* A catch clause was true */
1242  CAUGHT_NOTHING, /* No catch clauses were true */
1243  CAUGHT_ERROR /* A fatal error occured */
1244 } CatchState;
1245 
1246 CatchState catch_script_events(Script *sc);
1247 
1248 /*
1249  * The context member of each choice DataType will point to a object
1250  * different object of the following type. It contains the distinguishing
1251  * details of a given choice datatype.
1252  */
1253 typedef struct { /* The instance data of a 'choice' datatype */
1254  ScriptObj header; /* The required garbage collection header */
1255  Enumerator *choices; /* The 'nmember' name/value pairs */
1256  unsigned nchoice; /* The number of choices in choices[] */
1257 } ChoiceType;
1258 
1259 /*
1260  * The context member of each Set DataType will point to a object
1261  * different object of the following type. It contains the distinguishing
1262  * details of a given Set datatype.
1263  */
1264 typedef struct { /* The instance data of a 'set' datatype */
1265  ScriptObj header; /* The required garbage collection header */
1266  Enumerator *members; /* The 'nmember' name/value pairs */
1267  unsigned nmember; /* The number of set member values */
1268  unsigned all; /* The union of all set member values */
1269  unsigned nbit; /* The number of bits set in 'all' */
1270  int allow_bit_mask; /* True to allow users to type numeric bit masks */
1271  ScOperator *inc_op; /* An scoperator proc that includes bits to a set */
1272  ScOperator *exc_op; /* An scoperator proc that excludes bits from a set */
1273 } SetType;
1274 
1275 #endif
Definition: script.h:1052
Definition: script.h:1071
Definition: hash.h:119
Definition: script.h:1027
Definition: script.h:1020
Definition: hash.h:76
Definition: script.h:1094
Definition: script.h:557
Definition: script.h:529
Definition: statement.c:252
Definition: script.h:760
Definition: expr.c:133
Definition: script.h:1114
Definition: input.h:87
Definition: script.h:513
Definition: script.h:746
Definition: script.h:284
Definition: stringpool.c:23
Definition: script.h:601
Definition: hash.h:56
Definition: expr.c:155
Definition: script.h:1060
Definition: String.h:16
Definition: script.h:867
Definition: list.c:12
Definition: script.h:525
Definition: script.h:490
Definition: freelist.c:13
Definition: script.h:588
Definition: script.h:1045
Definition: script.h:315
Definition: script.h:250
Definition: script.h:1253
Definition: script.h:1082
Definition: script.h:178
Definition: script.h:1264
Definition: script.h:505
Definition: output.h:40
Definition: list.h:40
Definition: list.h:48
Definition: script.h:992
Definition: script.h:218
Definition: script.h:626
Definition: statement.c:227
Definition: script.h:1038
Definition: statement.c:143