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