cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

syntax.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 
25 #include <syntax.h>
26 
27 #include <json.h>
28 #include <files_names.h>
29 #include <mod_files.h>
30 #include <item_lib.h>
31 #include <conversion.h>
32 #include <expand.h>
33 #include <matching.h>
34 #include <scope.h>
35 #include <fncall.h>
36 #include <string_lib.h> /* IsStrIn */
37 #include <regex.h> /* StringMatchFull */
38 #include <misc_lib.h>
39 #include <rlist.h>
40 #include <vars.h>
41 #include <eval_context.h>
42 
43 
44 static SyntaxTypeMatch CheckParseString(const char *lv, const char *s, const char *range);
45 static SyntaxTypeMatch CheckParseInt(const char *lv, const char *s, const char *range);
46 static SyntaxTypeMatch CheckParseReal(const char *lv, const char *s, const char *range);
47 static SyntaxTypeMatch CheckParseRealRange(const char *lval, const char *s, const char *range);
48 static SyntaxTypeMatch CheckParseIntRange(const char *lval, const char *s, const char *range);
49 static SyntaxTypeMatch CheckParseOpts(const char *s, const char *range);
50 static SyntaxTypeMatch CheckFnCallType(const char *s, DataType dtype);
51 
52 /*********************************************************/
53 
54 static const PromiseTypeSyntax *PromiseTypeSyntaxGetStrict(const char *bundle_type, const char *promise_type)
55 {
56  assert(bundle_type != NULL);
57  assert(promise_type != NULL);
58 
59  for (int module_index = 0; module_index < CF3_MODULES; module_index++)
60  {
61  for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++)
62  {
63  const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index];
64 
65  if (strcmp(bundle_type, promise_type_syntax->bundle_type) == 0
66  && strcmp(promise_type, promise_type_syntax->promise_type) == 0)
67  {
68  return promise_type_syntax;
69  }
70  }
71  }
72  return NULL;
73 }
74 
75 const PromiseTypeSyntax *PromiseTypeSyntaxGet(const char *bundle_type, const char *promise_type)
76 {
77  const PromiseTypeSyntax *pts = PromiseTypeSyntaxGetStrict(bundle_type, promise_type);
78  if (!pts)
79  {
80  pts = PromiseTypeSyntaxGetStrict("*", promise_type);
81  }
82  return pts;
83 }
84 
85 static const ConstraintSyntax *GetCommonConstraint(const char *lval)
86 {
87  for (int i = 0; CF_COMMON_PROMISE_TYPES[i].promise_type; i++)
88  {
89  const PromiseTypeSyntax promise_type_syntax = CF_COMMON_PROMISE_TYPES[i];
90 
91  for (int j = 0; promise_type_syntax.constraints[j].lval; j++)
92  {
93  if (strcmp(promise_type_syntax.constraints[j].lval, lval) == 0)
94  {
95  return &promise_type_syntax.constraints[j];
96  }
97  }
98  }
99 
100  return NULL;
101 }
102 
103 const ConstraintSyntax *BodySyntaxGetConstraintSyntax(const ConstraintSyntax *body_syntax, const char *lval)
104 {
105  for (int j = 0; body_syntax[j].lval; j++)
106  {
107  if (strcmp(body_syntax[j].lval, lval) == 0)
108  {
109  return &body_syntax[j];
110  }
111  }
112  return NULL;
113 }
114 
115 const ConstraintSyntax *PromiseTypeSyntaxGetConstraintSyntax(const PromiseTypeSyntax *promise_type_syntax, const char *lval)
116 {
117  assert(promise_type_syntax != NULL);
118  assert(lval != NULL);
119 
120  for (int i = 0; promise_type_syntax->constraints[i].lval; i++)
121  {
122  if (strcmp(promise_type_syntax->constraints[i].lval, lval) == 0)
123  {
124  return &promise_type_syntax->constraints[i];
125  }
126  }
127 
128  const ConstraintSyntax *constraint_syntax = NULL;
129  if (strcmp("edit_line", promise_type_syntax->bundle_type) == 0)
130  {
131  constraint_syntax = BodySyntaxGetConstraintSyntax(CF_COMMON_EDITBODIES, lval);
132  if (constraint_syntax)
133  {
134  return constraint_syntax;
135  }
136  }
137  else if (strcmp("edit_xml", promise_type_syntax->bundle_type) == 0)
138  {
139  constraint_syntax = BodySyntaxGetConstraintSyntax(CF_COMMON_XMLBODIES, lval);
140  if (constraint_syntax)
141  {
142  return constraint_syntax;
143  }
144  }
145 
146  return GetCommonConstraint(lval);
147 }
148 
149 const BodySyntax *BodySyntaxGet(const char *body_type)
150 {
151  for (int i = 0; i < CF3_MODULES; i++)
152  {
153  const PromiseTypeSyntax *promise_type_syntax = CF_ALL_PROMISE_TYPES[i];
154 
155  for (int k = 0; promise_type_syntax[k].bundle_type != NULL; k++)
156  {
157  for (int z = 0; promise_type_syntax[k].constraints[z].lval != NULL; z++)
158  {
159  const ConstraintSyntax constraint_syntax = promise_type_syntax[k].constraints[z];
160 
161  if (constraint_syntax.dtype == CF_DATA_TYPE_BODY && strcmp(body_type, constraint_syntax.lval) == 0)
162  {
163  return constraint_syntax.range.body_type_syntax;
164  }
165  }
166  }
167  }
168 
169  for (int i = 0; CONTROL_BODIES[i].body_type != NULL; i++)
170  {
171  const BodySyntax body_syntax = CONTROL_BODIES[i];
172 
173  if (strcmp(body_type, body_syntax.body_type) == 0)
174  {
175  return &CONTROL_BODIES[i];
176  }
177  }
178 
179  return NULL;
180 }
181 
183 {
184  assert( status == SYNTAX_STATUS_DEPRECATED ||
185  status == SYNTAX_STATUS_NORMAL ||
186  status == SYNTAX_STATUS_REMOVED );
187  switch (status)
188  {
190  return "deprecated";
192  return "normal";
194  return "removed";
195  default:
196  break;
197  }
198  return NULL;
199 }
200 
201 /****************************************************************************/
202 
203 DataType ExpectedDataType(const char *lvalname)
204 {
205  int i, j, k, l;
206  const ConstraintSyntax *bs, *bs2;
207  const PromiseTypeSyntax *ss;
208 
209  for (i = 0; i < CF3_MODULES; i++)
210  {
211  if ((ss = CF_ALL_PROMISE_TYPES[i]) == NULL)
212  {
213  continue;
214  }
215 
216  for (j = 0; ss[j].promise_type != NULL; j++)
217  {
218  if ((bs = ss[j].constraints) == NULL)
219  {
220  continue;
221  }
222 
223  for (k = 0; bs[k].lval != NULL; k++)
224  {
225  if (strcmp(lvalname, bs[k].lval) == 0)
226  {
227  return bs[k].dtype;
228  }
229  }
230 
231  for (k = 0; bs[k].lval != NULL; k++)
232  {
233  if (bs[k].dtype == CF_DATA_TYPE_BODY)
234  {
235  bs2 = bs[k].range.body_type_syntax->constraints;
236 
237  if (bs2 == NULL || bs2 == (void *) CF_BUNDLE)
238  {
239  continue;
240  }
241 
242  for (l = 0; bs2[l].dtype != CF_DATA_TYPE_NONE; l++)
243  {
244  if (strcmp(lvalname, bs2[l].lval) == 0)
245  {
246  return bs2[l].dtype;
247  }
248  }
249  }
250  }
251 
252  }
253  }
254 
255  return CF_DATA_TYPE_NONE;
256 }
257 
258 /****************************************************************************/
259 /* Level 1 */
260 /****************************************************************************/
261 
263 {
264  assert(result < SYNTAX_TYPE_MATCH_MAX);
265 
266  static const char *const msgs[SYNTAX_TYPE_MATCH_MAX] =
267  {
268  [SYNTAX_TYPE_MATCH_OK] = "OK",
269 
270  [SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED] = "Cannot check unexpanded value",
271  [SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED] = "Real range specification should not be enclosed in brackets - just 'a,b'",
272  [SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS] = "Range format specifier should be of form 'a,b'' but got multiple items",
273  [SYNTAX_TYPE_MATCH_ERROR_GOT_SCALAR] = "Attempted to give a scalar to a non-scalar type",
274  [SYNTAX_TYPE_MATCH_ERROR_GOT_LIST] = "Attempted to give a list to a non-list type",
275  [SYNTAX_TYPE_MATCH_ERROR_GOT_NULL] = "Attempted to give a value of type null",
276 
277  [SYNTAX_TYPE_MATCH_ERROR_STRING_UNIX_PERMISSION] = "Error parsing Unix permission string",
278 
279  [SYNTAX_TYPE_MATCH_ERROR_SCALAR_OUT_OF_RANGE] = "Scalar value is out of range",
280  [SYNTAX_TYPE_MATCH_ERROR_EMPTY_SCALAR_OUT_OF_RANGE] = "Empty scalar value is out of range",
281 
282  [SYNTAX_TYPE_MATCH_ERROR_INT_PARSE] = "Cannot parse value as integer",
283  [SYNTAX_TYPE_MATCH_ERROR_INT_OUT_OF_RANGE] = "Integer is out of range",
284 
285  [SYNTAX_TYPE_MATCH_ERROR_REAL_INF] = "Keyword 'inf' has an integer value, cannot be used as real",
286  [SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE] = "Real value is out of range",
287 
288  [SYNTAX_TYPE_MATCH_ERROR_OPTS_OUT_OF_RANGE] = "Selection is out of bounds",
289 
290  [SYNTAX_TYPE_MATCH_ERROR_FNCALL_RETURN_TYPE] = "Function does not return the required type",
291  [SYNTAX_TYPE_MATCH_ERROR_FNCALL_UNKNOWN] = "Unknown function",
292 
293  [SYNTAX_TYPE_MATCH_ERROR_CONTEXT_OUT_OF_RANGE] = "Context string is invalid/out of range",
294  [SYNTAX_TYPE_MATCH_ERROR_ABSOLUTE_PATH] = "Filename is not an absolute path",
295  };
296 
297  return msgs[result];
298 }
299 
300 SyntaxTypeMatch CheckConstraintTypeMatch(const char *lval, Rval rval, DataType dt, const char *range, int level)
301 {
302  Rlist *rp;
303  Item *checklist;
304 
305 /* Get type of lval */
306 
307  switch (rval.type)
308  {
309  case RVAL_TYPE_SCALAR:
310  switch (dt)
311  {
317  if (level == 0)
318  {
320  }
321  break;
322  default:
323  /* Only lists are incompatible with scalars */
324  break;
325  }
326  break;
327 
328  case RVAL_TYPE_LIST:
329 
330  switch (dt)
331  {
337  break;
338  default:
340  }
341 
342  for (rp = (Rlist *) rval.item; rp != NULL; rp = rp->next)
343  {
344  SyntaxTypeMatch err = CheckConstraintTypeMatch(lval, rp->val, dt, range, 1);
345  switch (err)
346  {
349  break;
350 
351  default:
352  return err;
353  }
354  }
355 
356  return SYNTAX_TYPE_MATCH_OK;
357 
358  case RVAL_TYPE_FNCALL:
359 
360  /* Fn-like objects are assumed to be parameterized bundles in these... */
361 
362  checklist = SplitString("bundlesequence,edit_line,edit_xml,usebundle,service_bundle,home_bundle", ',');
363 
364  if (!IsItemIn(checklist, lval))
365  {
366  SyntaxTypeMatch err = CheckFnCallType(RvalFnCallValue(rval)->name, dt);
367  DeleteItemList(checklist);
368  return err;
369  }
370 
371  DeleteItemList(checklist);
372  return SYNTAX_TYPE_MATCH_OK;
373 
374  case RVAL_TYPE_CONTAINER:
375  break;
376 
379  }
380 
381 /* If we get here, we have a literal scalar type */
382 
383  switch (dt)
384  {
385  case CF_DATA_TYPE_STRING:
387  return CheckParseString(lval, (const char *) rval.item, range);
388 
389  case CF_DATA_TYPE_INT:
391  return CheckParseInt(lval, (const char *) rval.item, range);
392 
393  case CF_DATA_TYPE_REAL:
395  return CheckParseReal(lval, (const char *) rval.item, range);
396 
397  case CF_DATA_TYPE_BODY:
398  case CF_DATA_TYPE_BUNDLE:
400  break;
401 
402  case CF_DATA_TYPE_OPTION:
404  return CheckParseOpts(RvalScalarValue(rval), range);
405 
408  return CheckParseContext((const char *) rval.item, range);
409 
411  return CheckParseIntRange(lval, (const char *) rval.item, range);
412 
414  return CheckParseRealRange(lval, (char *) rval.item, range);
415 
416  default:
417  ProgrammingError("Unknown (unhandled) datatype for lval = %s (CheckConstraintTypeMatch)", lval);
418  break;
419  }
420 
421  return SYNTAX_TYPE_MATCH_OK;
422 }
423 
424 /****************************************************************************/
425 
426 DataType StringDataType(EvalContext *ctx, const char *string)
427 {
428  int islist = false; /* TODO something is wrong here */
429 
430 /*-------------------------------------------------------
431 What happens if we embed vars in a literal string
432  "$(list)withending" - a list?
433  "$(list1)$(list2)" - not a simple list
434 Disallow these manual concatenations as ambiguous.
435 Demand this syntax to work around
436 
437 vars:
438 
439  "listvar" slist => EmbellishList("prefix$(list)suffix");
440 ---------------------------------------------------------*/
441 
442  size_t len = strlen(string);
443 
444  if (*string == '$')
445  {
446  Buffer *inner_value = BufferNew();
447  if (ExtractScalarReference(inner_value, string, len, true))
448  {
449  DataType dtype;
450  if (!IsExpandable(BufferData(inner_value)))
451  {
452  VarRef *ref = VarRefParse(BufferData(inner_value));
453  EvalContextVariableGet(ctx, ref, &dtype);
454  VarRefDestroy(ref);
455 
456  if (DataTypeToRvalType(dtype) == RVAL_TYPE_LIST)
457  {
458  if (!islist)
459  {
460  islist = true;
461  }
462  else
463  {
464  islist = false;
465  }
466  }
467  }
468 
469  if (BufferSize(inner_value) == strlen(string))
470  {
471  BufferDestroy(inner_value);
472  return dtype;
473  }
474  else
475  {
476  BufferDestroy(inner_value);
477  return CF_DATA_TYPE_STRING;
478  }
479  }
480 
481  BufferDestroy(inner_value);
482  }
483 
484  return CF_DATA_TYPE_STRING;
485 }
486 
487 /****************************************************************************/
488 /* Level 1 */
489 /****************************************************************************/
490 
491 static SyntaxTypeMatch CheckParseString(const char *lval, const char *s, const char *range)
492 {
493  if (s == NULL)
494  {
495  return SYNTAX_TYPE_MATCH_OK;
496  }
497 
498  if (strlen(range) == 0)
499  {
500  return SYNTAX_TYPE_MATCH_OK;
501  }
502 
503  if (IsNakedVar(s, '@') || IsNakedVar(s, '$'))
504  {
506  }
507 
508 /* Deal with complex strings as special cases */
509 
510  if (strcmp(lval, "mode") == 0 || strcmp(lval, "search_mode") == 0)
511  {
512  mode_t plus, minus;
513 
514  if (!ParseModeString(s, &plus, &minus))
515  {
517  }
518  }
519 
520  /* FIXME: review this strcmp. Moved out from StringMatch */
521  if (!strcmp(range, s) || StringMatchFull(range, s))
522  {
523  return SYNTAX_TYPE_MATCH_OK;
524  }
525 
526  if (IsCf3VarString(s))
527  {
529  }
530  else if ('\0' == s[0])
531  {
533  }
534  else if (!strcmp(range, CF_ABSPATHRANGE))
535  {
537  }
538  else
539  {
541  }
542 
543  return SYNTAX_TYPE_MATCH_OK;
544 }
545 
546 /****************************************************************************/
547 
548 SyntaxTypeMatch CheckParseContext(const char *context, const char *range)
549 {
550  if (strlen(range) == 0)
551  {
552  return SYNTAX_TYPE_MATCH_OK;
553  }
554 
555  /* FIXME: review this strcmp. Moved out from StringMatch */
556  if (!strcmp(range, context) || StringMatchFull(range, context))
557  {
558  return SYNTAX_TYPE_MATCH_OK;
559  }
560 
562 }
563 
564 /****************************************************************************/
565 
566 static SyntaxTypeMatch CheckParseInt(const char *lval, const char *s, const char *range)
567 {
568  Item *split;
569  int n;
570  long long max = CF_LOWINIT, min = CF_HIGHINIT;
571 
572  // Numeric types are registered by range separated by comma str "min,max"
573  split = SplitString(range, ',');
574 
575  if ((n = ListLen(split)) != 2)
576  {
577  ProgrammingError("INTERN: format specifier for int rvalues is not ok for lval %s - got %d items", lval, n);
578  }
579 
580  sscanf(split->name, "%lld", &min);
581 
582  if (strcmp(split->next->name, "inf") == 0)
583  {
584  max = CF_INFINITY;
585  }
586  else
587  {
588  sscanf(split->next->name, "%lld", &max);
589  }
590 
591  DeleteItemList(split);
592 
593  if (min == CF_HIGHINIT || max == CF_LOWINIT)
594  {
595  ProgrammingError("INTERN: could not parse format specifier for int rvalues for lval %s", lval);
596  }
597 
598  if (IsCf3VarString(s))
599  {
601  }
602 
603  long val = IntFromString(s);
604 
605  if (val == CF_NOINT)
606  {
608  }
609 
610  if (val > max || val < min)
611  {
613  }
614 
615  return SYNTAX_TYPE_MATCH_OK;
616 }
617 
618 /****************************************************************************/
619 
620 static SyntaxTypeMatch CheckParseIntRange(const char *lval, const char *s, const char *range)
621 {
622  Item *split, *ip, *rangep;
623  int n;
624  long long max = CF_LOWINIT, min = CF_HIGHINIT;
625 
626  // Numeric types are registered by range separated by comma str "min,max"
627  if (*s == '[' || *s == '(')
628  {
630  }
631 
632  split = SplitString(range, ',');
633 
634  if ((n = ListLen(split)) != 2)
635  {
636  ProgrammingError("Format specifier %s for irange rvalues is not ok for lval %s - got %d items", range, lval, n);
637  }
638 
639  sscanf(split->name, "%lld", &min);
640 
641  if (strcmp(split->next->name, "inf") == 0)
642  {
643  max = CF_INFINITY;
644  }
645  else
646  {
647  sscanf(split->next->name, "%lld", &max);
648  }
649 
650  DeleteItemList(split);
651 
652  if (min == CF_HIGHINIT || max == CF_LOWINIT)
653  {
654  ProgrammingError("Could not parse irange format specifier for int rvalues for lval %s", lval);
655  }
656 
657  if (IsCf3VarString(s))
658  {
660  }
661 
662  rangep = SplitString(s, ',');
663 
664  if ((n = ListLen(rangep)) != 2)
665  {
667  }
668 
669  for (ip = rangep; ip != NULL; ip = ip->next)
670  {
671  long val = IntFromString(ip->name);
672 
673  if (val > max || val < min)
674  {
676  }
677  }
678 
679  DeleteItemList(rangep);
680 
681  return SYNTAX_TYPE_MATCH_OK;
682 }
683 
684 /****************************************************************************/
685 
686 static SyntaxTypeMatch CheckParseReal(const char *lval, const char *s, const char *range)
687 {
688  Item *split;
689  double max = (double) CF_LOWINIT, min = (double) CF_HIGHINIT, val;
690  int n;
691 
692  if (strcmp(s, "inf") == 0)
693  {
695  }
696 
697  if (IsCf3VarString(s))
698  {
700  }
701 
702 /* Numeric types are registered by range separated by comma str "min,max" */
703 
704  split = SplitString(range, ',');
705 
706  if ((n = ListLen(split)) != 2)
707  {
708  ProgrammingError("Format specifier for real rvalues is not ok for lval %s - %d items", lval, n);
709  }
710 
711  sscanf(split->name, "%lf", &min);
712  sscanf(split->next->name, "%lf", &max);
713  DeleteItemList(split);
714 
715  if (min == CF_HIGHINIT || max == CF_LOWINIT)
716  {
717  ProgrammingError("Could not parse format specifier for int rvalues for lval %s", lval);
718  }
719 
720  if (!DoubleFromString(s, &val))
721  {
723  }
724 
725  if (val > max || val < min)
726  {
728  }
729 
730  return SYNTAX_TYPE_MATCH_OK;
731 }
732 
733 /****************************************************************************/
734 
735 static SyntaxTypeMatch CheckParseRealRange(const char *lval, const char *s, const char *range)
736 {
737  Item *split, *rangep, *ip;
738  double max = (double) CF_LOWINIT, min = (double) CF_HIGHINIT, val;
739  int n;
740 
741  if (*s == '[' || *s == '(')
742  {
744  }
745 
746  if (strcmp(s, "inf") == 0)
747  {
749  }
750 
751  if (IsCf3VarString(s))
752  {
754  }
755 
756 /* Numeric types are registered by range separated by comma str "min,max" */
757 
758  split = SplitString(range, ',');
759 
760  if ((n = ListLen(split)) != 2)
761  {
762  ProgrammingError("Format specifier for real rvalues is not ok for lval %s - %d items", lval, n);
763  }
764 
765  sscanf(split->name, "%lf", &min);
766  sscanf(split->next->name, "%lf", &max);
767  DeleteItemList(split);
768 
769  if (min == CF_HIGHINIT || max == CF_LOWINIT)
770  {
771  ProgrammingError("Could not parse format specifier for int rvalues for lval %s", lval);
772  }
773 
774  rangep = SplitString(s, ',');
775 
776  if ((n = ListLen(rangep)) != 2)
777  {
779  }
780 
781  for (ip = rangep; ip != NULL; ip = ip->next)
782  {
783  if (!DoubleFromString(ip->name, &val))
784  {
786  }
787 
788  if (val > max || val < min)
789  {
791  }
792  }
793 
794  DeleteItemList(rangep);
795 
796  return SYNTAX_TYPE_MATCH_OK;
797 }
798 
799 /****************************************************************************/
800 
801 static SyntaxTypeMatch CheckParseOpts(const char *s, const char *range)
802 {
803  Item *split;
804 
805 /* List/menu types are separated by comma str "a,b,c,..." */
806 
807  if (IsNakedVar(s, '@') || IsNakedVar(s, '$'))
808  {
810  }
811 
812  split = SplitString(range, ',');
813 
814  if (!IsItemIn(split, s))
815  {
816  DeleteItemList(split);
818  }
819 
820  DeleteItemList(split);
821 
822  return SYNTAX_TYPE_MATCH_OK;
823 }
824 
825 /****************************************************************************/
826 
827 bool CheckParseVariableName(const char *const name)
828 {
829  assert(name != NULL);
830 
831  const char *const reserved[] = {
832  "promiser",
833  "handle",
834  "promise_filename",
835  "promise_dirname",
836  "promise_linenumber",
837  "this",
838  NULL
839  };
840 
841  if (IsStrIn(name, reserved))
842  {
843  return false;
844  }
845 
846  int count = 0, level = 0;
847 
848  const char *const first_dot = strchr(name, '.');
849 
850  if (first_dot != NULL)
851  {
852  for (const char *sp = name; *sp != '\0'; sp++)
853  {
854  switch (*sp)
855  {
856  case '.':
857  count++;
858  if (count > 1 && level != 1)
859  {
860  // Adding a second dot is not allowed,
861  // except inside 1 level of square brackets
862  return false;
863  }
864  break;
865 
866  case '[':
867  level++;
868  break;
869 
870  case ']':
871  level--;
872  break;
873 
874  default:
875  break;
876  }
877 
878  if (level > 1)
879  {
880  yyerror("Too many levels of [] reserved for array use");
881  return false;
882  }
883  }
884 
885  if (count == 1)
886  {
887  // Check that there is something before and after first dot:
888  if (name[0] == '.' || first_dot[1] == '\0')
889  {
890  return false;
891  }
892  }
893  }
894 
895  return true;
896 }
897 
898 /****************************************************************************/
899 
900 static SyntaxTypeMatch CheckFnCallType(const char *s, DataType dtype)
901 {
902  DataType dt;
903  const FnCallType *fn;
904 
905  fn = FnCallTypeGet(s);
906 
907  if (fn)
908  {
909  dt = fn->dtype;
910 
911  if (dtype != dt)
912  {
913  /* Ok to allow fn calls of correct element-type in lists */
914 
915  if (dt == CF_DATA_TYPE_STRING && dtype == CF_DATA_TYPE_STRING_LIST)
916  {
917  return SYNTAX_TYPE_MATCH_OK;
918  }
919 
920  if (dt == CF_DATA_TYPE_STRING && dtype == CF_DATA_TYPE_CONTEXT)
921  {
922  return SYNTAX_TYPE_MATCH_OK;
923  }
924 
925  if (dt == CF_DATA_TYPE_INT && dtype == CF_DATA_TYPE_INT_LIST)
926  {
927  return SYNTAX_TYPE_MATCH_OK;
928  }
929 
930  if (dt == CF_DATA_TYPE_REAL && dtype == CF_DATA_TYPE_REAL_LIST)
931  {
932  return SYNTAX_TYPE_MATCH_OK;
933  }
934 
935  if (dt == CF_DATA_TYPE_OPTION && dtype == CF_DATA_TYPE_OPTION_LIST)
936  {
937  return SYNTAX_TYPE_MATCH_OK;
938  }
939 
940  if (dt == CF_DATA_TYPE_CONTEXT && dtype == CF_DATA_TYPE_CONTEXT_LIST)
941  {
942  return SYNTAX_TYPE_MATCH_OK;
943  }
944 
946  }
947  else
948  {
949  return SYNTAX_TYPE_MATCH_OK;
950  }
951  }
952  else
953  {
955  }
956 }
957 
958 
959 /****************************************************************************/
960 
961 static JsonElement *ConstraintSyntaxToJson(const ConstraintSyntax *constraint_syntax)
962 {
963  JsonElement *json_constraint = JsonObjectCreate(5);
964 
965  JsonObjectAppendString(json_constraint, "attribute", constraint_syntax->lval);
966  JsonObjectAppendString(json_constraint, "status", SyntaxStatusToString(constraint_syntax->status));
967  JsonObjectAppendString(json_constraint, "type", DataTypeToString(constraint_syntax->dtype));
968 
969  if (constraint_syntax->dtype != CF_DATA_TYPE_BODY && constraint_syntax->dtype != CF_DATA_TYPE_BUNDLE)
970  {
971  JsonObjectAppendString(json_constraint, "range", constraint_syntax->range.validation_string);
972  }
973 
974  return json_constraint;
975 }
976 
977 static JsonElement *BodySyntaxToJson(const BodySyntax *body_syntax)
978 {
979  JsonElement *json_body = JsonObjectCreate(2);
980 
981  JsonObjectAppendString(json_body, "status", SyntaxStatusToString(body_syntax->status));
982  {
983  JsonElement *attributes = JsonObjectCreate(50);
984 
985  for (int i = 0; body_syntax->constraints[i].lval; i++)
986  {
987  const ConstraintSyntax *constraint_syntax = &body_syntax->constraints[i];
988  if (constraint_syntax->status != SYNTAX_STATUS_REMOVED)
989  {
990  JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax);
991  JsonObjectAppendString(json_constraint, "visibility", "body");
992  JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint);
993  }
994  }
995 
996  JsonObjectAppendObject(json_body, "attributes", attributes);
997  }
998 
999  return json_body;
1000 }
1001 
1003 {
1004  JsonElement *json_bundle_type = JsonObjectCreate(2);
1005 
1007  JsonObjectAppendArray(json_bundle_type, "promiseTypes", JsonArrayCreate(50));
1008 
1009  return json_bundle_type;
1010 }
1011 
1013 {
1014  JsonElement *bundle_types = JsonObjectCreate(50);
1015 
1016  Seq *common_promise_types = SeqNew(50, free);
1017 
1018  for (int module_index = 0; module_index < CF3_MODULES; module_index++)
1019  {
1020  for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++)
1021  {
1022  const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index];
1023 
1024  // skip global constraints
1025  if (strcmp("*", promise_type_syntax->promise_type) == 0)
1026  {
1027  continue;
1028  }
1029 
1030  // collect common promise types to be appended at the end
1031  if (strcmp("*", promise_type_syntax->bundle_type) == 0)
1032  {
1033  SeqAppend(common_promise_types, xstrdup(promise_type_syntax->promise_type));
1034  continue;
1035  }
1036 
1037  if (promise_type_syntax->status == SYNTAX_STATUS_REMOVED)
1038  {
1039  continue;
1040  }
1041 
1042  JsonElement *bundle_type = JsonObjectGet(bundle_types, promise_type_syntax->bundle_type);
1043  if (!bundle_type)
1044  {
1045  bundle_type = JsonBundleTypeNew();
1046  JsonObjectAppendObject(bundle_types, promise_type_syntax->bundle_type, bundle_type);
1047  }
1048  assert(bundle_type);
1049 
1050  JsonElement *promise_types = JsonObjectGet(bundle_type, "promiseTypes");
1051  assert(promise_types);
1052 
1053  JsonArrayAppendString(promise_types, promise_type_syntax->promise_type);
1054  }
1055  }
1056 
1057  // Append the common bundle, which has only common promise types, but is not declared in syntax
1058  {
1059  JsonElement *bundle_type = JsonBundleTypeNew();
1060  JsonObjectAppendObject(bundle_types, "common", bundle_type);
1061  }
1062 
1063  JsonIterator it = JsonIteratorInit(bundle_types);
1064  const char *bundle_type = NULL;
1065  while ((bundle_type = JsonIteratorNextKey(&it)))
1066  {
1067  JsonElement *promise_types = JsonObjectGetAsArray(JsonObjectGetAsObject(bundle_types, bundle_type), "promiseTypes");
1068  for (int i = 0; i < SeqLength(common_promise_types); i++)
1069  {
1070  const char *common_promise_type = SeqAt(common_promise_types, i);
1071  JsonArrayAppendString(promise_types, common_promise_type);
1072  }
1073  }
1074 
1075  SeqDestroy(common_promise_types);
1076  return bundle_types;
1077 }
1078 
1080 {
1081  JsonElement *promise_type = JsonObjectCreate(2);
1082 
1083  JsonObjectAppendString(promise_type, "status", SyntaxStatusToString(status));
1084  JsonObjectAppendObject(promise_type, "attributes", JsonObjectCreate(50));
1085 
1086  return promise_type;
1087 }
1088 
1090 {
1091  JsonElement *promise_types = JsonObjectCreate(50);
1092 
1093  const PromiseTypeSyntax *global_promise_type = PromiseTypeSyntaxGet("*", "*");
1094 
1095  for (int module_index = 0; module_index < CF3_MODULES; module_index++)
1096  {
1097  for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++)
1098  {
1099  const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index];
1100 
1101  // skip global and bundle-local common constraints
1102  if (strcmp("*", promise_type_syntax->promise_type) == 0)
1103  {
1104  continue;
1105  }
1106 
1107  if (promise_type_syntax->status == SYNTAX_STATUS_REMOVED)
1108  {
1109  continue;
1110  }
1111 
1112  JsonElement *promise_type = JsonObjectGet(promise_types, promise_type_syntax->promise_type);
1113  if (!promise_type)
1114  {
1115  promise_type = JsonPromiseTypeNew(promise_type_syntax->status);
1116  JsonObjectAppendObject(promise_types, promise_type_syntax->promise_type, promise_type);
1117  }
1118  assert(promise_type);
1119 
1120  JsonElement *attributes = JsonObjectGet(promise_type, "attributes");
1121  assert(attributes);
1122 
1123  for (int i = 0; promise_type_syntax->constraints[i].lval; i++)
1124  {
1125  const ConstraintSyntax *constraint_syntax = &promise_type_syntax->constraints[i];
1126  JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax);
1127  JsonObjectAppendString(json_constraint, "visibility", "promiseType");
1128  JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint);
1129  }
1130 
1131  // append bundle common constraints
1132  const PromiseTypeSyntax *bundle_promise_type = PromiseTypeSyntaxGet(promise_type_syntax->bundle_type, "*");
1133  if (strcmp("*", bundle_promise_type->bundle_type) != 0)
1134  {
1135  for (int i = 0; bundle_promise_type->constraints[i].lval; i++)
1136  {
1137  const ConstraintSyntax *constraint_syntax = &bundle_promise_type->constraints[i];
1138  JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax);
1139  JsonObjectAppendString(json_constraint, "visibility", "bundle");
1140  JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint);
1141  }
1142  }
1143 
1144  // append global common constraints
1145  for (int i = 0; global_promise_type->constraints[i].lval; i++)
1146  {
1147  const ConstraintSyntax *constraint_syntax = &global_promise_type->constraints[i];
1148  JsonElement *json_constraint = ConstraintSyntaxToJson(constraint_syntax);
1149  JsonObjectAppendString(json_constraint, "visibility", "global");
1150  JsonObjectAppendObject(attributes, constraint_syntax->lval, json_constraint);
1151  }
1152  }
1153  }
1154 
1155  return promise_types;
1156 }
1157 
1159 {
1160  JsonElement *body_types = JsonObjectCreate(50);
1161 
1162  for (int module_index = 0; module_index < CF3_MODULES; module_index++)
1163  {
1164  for (int promise_type_index = 0; CF_ALL_PROMISE_TYPES[module_index][promise_type_index].promise_type; promise_type_index++)
1165  {
1166  const PromiseTypeSyntax *promise_type_syntax = &CF_ALL_PROMISE_TYPES[module_index][promise_type_index];
1167 
1168  for (int constraint_index = 0; promise_type_syntax->constraints[constraint_index].lval; constraint_index++)
1169  {
1170  const ConstraintSyntax *constraint_syntax = &promise_type_syntax->constraints[constraint_index];
1171  if (constraint_syntax->dtype != CF_DATA_TYPE_BODY)
1172  {
1173  continue;
1174  }
1175 
1176  if (constraint_syntax->status == SYNTAX_STATUS_REMOVED)
1177  {
1178  continue;
1179  }
1180 
1181  const BodySyntax *body_syntax = constraint_syntax->range.body_type_syntax;
1182  JsonElement *body_type = JsonObjectGet(body_types, body_syntax->body_type);
1183  if (!body_type)
1184  {
1185  JsonElement *body_type = BodySyntaxToJson(body_syntax);
1186  JsonObjectAppendObject(body_types, body_syntax->body_type, body_type);
1187  }
1188  }
1189  }
1190  }
1191 
1192  for (int i = 0; CONTROL_BODIES[i].body_type; i++)
1193  {
1194  const BodySyntax *body_syntax = &CONTROL_BODIES[i];
1195 
1196  if (body_syntax->status == SYNTAX_STATUS_REMOVED)
1197  {
1198  continue;
1199  }
1200 
1201  JsonElement *body_type = JsonObjectGet(body_types, body_syntax->body_type);
1202  if (!body_type)
1203  {
1204  JsonElement *body_type = BodySyntaxToJson(body_syntax);
1205  JsonObjectAppendObject(body_types, body_syntax->body_type, body_type);
1206  }
1207  }
1208 
1209  return body_types;
1210 }
1211 
1212 static const char *FnCallCategoryToString(FnCallCategory category)
1213 {
1214  static const char *const category_str[] =
1215  {
1216  [FNCALL_CATEGORY_COMM] = "communication",
1217  [FNCALL_CATEGORY_DATA] = "data",
1218  [FNCALL_CATEGORY_FILES] = "files",
1219  [FNCALL_CATEGORY_IO] = "io",
1220  [FNCALL_CATEGORY_SYSTEM] = "system",
1221  [FNCALL_CATEGORY_UTILS] = "utils",
1222  [FNCALL_CATEGORY_INTERNAL] = "internal"
1223  };
1224 
1225  return category_str[category];
1226 }
1227 
1228 static JsonElement *FnCallTypeToJson(const FnCallType *fn_syntax)
1229 {
1230  JsonElement *json_fn = JsonObjectCreate(10);
1231 
1232  JsonObjectAppendString(json_fn, "status", SyntaxStatusToString(fn_syntax->status));
1233  JsonObjectAppendString(json_fn, "returnType", DataTypeToString(fn_syntax->dtype));
1234 
1235  {
1236  JsonElement *params = JsonArrayCreate(10);
1237  for (int i = 0; fn_syntax->args[i].pattern; i++)
1238  {
1239  const FnCallArg *param = &fn_syntax->args[i];
1240 
1241  JsonElement *json_param = JsonObjectCreate(2);
1242  JsonObjectAppendString(json_param, "type", DataTypeToString(param->dtype));
1243  JsonObjectAppendString(json_param, "range", param->pattern);
1244  JsonObjectAppendString(json_param, "description", param->description);
1245  JsonArrayAppendObject(params, json_param);
1246  }
1247  JsonObjectAppendArray(json_fn, "parameters", params);
1248  }
1249 
1250  JsonObjectAppendBool(json_fn, "variadic", fn_syntax->options & FNCALL_OPTION_VARARG);
1251  JsonObjectAppendBool(json_fn, "cached", fn_syntax->options & FNCALL_OPTION_CACHED);
1252  JsonObjectAppendBool(json_fn, "collecting", fn_syntax->options & FNCALL_OPTION_COLLECTING);
1253  JsonObjectAppendString(json_fn, "category", FnCallCategoryToString(fn_syntax->category));
1254 
1255  return json_fn;
1256 }
1257 
1259 {
1260  JsonElement *functions = JsonObjectCreate(500);
1261 
1262  for (int i = 0; CF_FNCALL_TYPES[i].name; i++)
1263  {
1264  const FnCallType *fn_syntax = &CF_FNCALL_TYPES[i];
1265 
1266  if (fn_syntax->status == SYNTAX_STATUS_REMOVED)
1267  {
1268  continue;
1269  }
1270 
1271  JsonObjectAppendObject(functions, fn_syntax->name, FnCallTypeToJson(fn_syntax));
1272  }
1273 
1274  return functions;
1275 }
1276 
1278 {
1279  JsonElement *syntax_tree = JsonObjectCreate(3);
1280 
1281  JsonObjectAppendObject(syntax_tree, "bundleTypes", BundleTypesToJson());
1282  JsonObjectAppendObject(syntax_tree, "promiseTypes", PromiseTypesToJson());
1283  JsonObjectAppendObject(syntax_tree, "bodyTypes", BodyTypesToJson());
1284  JsonObjectAppendObject(syntax_tree, "functions", FunctionsToJson());
1285 
1286  return syntax_tree;
1287 }
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
void BufferDestroy(Buffer *buffer)
Destroys a buffer and frees the memory associated with it.
Definition: buffer.c:72
Buffer * BufferNew(void)
Buffer initialization routine.
Definition: buffer.c:48
const char * BufferData(const Buffer *buffer)
Provides a pointer to the internal data.
Definition: buffer.c:470
unsigned int BufferSize(const Buffer *buffer)
Returns the size of the buffer.
Definition: buffer.c:464
#define CF_HIGHINIT
Definition: cf3.defs.h:551
const BodySyntax CONTROL_BODIES[]
Definition: mod_common.c:458
FnCallCategory
Definition: cf3.defs.h:644
@ FNCALL_CATEGORY_FILES
Definition: cf3.defs.h:646
@ FNCALL_CATEGORY_IO
Definition: cf3.defs.h:647
@ FNCALL_CATEGORY_UTILS
Definition: cf3.defs.h:650
@ FNCALL_CATEGORY_SYSTEM
Definition: cf3.defs.h:645
@ FNCALL_CATEGORY_INTERNAL
Definition: cf3.defs.h:651
@ FNCALL_CATEGORY_COMM
Definition: cf3.defs.h:648
@ FNCALL_CATEGORY_DATA
Definition: cf3.defs.h:649
#define CF_ABSPATHRANGE
Definition: cf3.defs.h:583
@ RVAL_TYPE_CONTAINER
Definition: cf3.defs.h:609
@ RVAL_TYPE_LIST
Definition: cf3.defs.h:607
@ RVAL_TYPE_SCALAR
Definition: cf3.defs.h:606
@ RVAL_TYPE_FNCALL
Definition: cf3.defs.h:608
@ RVAL_TYPE_NOPROMISEE
Definition: cf3.defs.h:610
const int CF3_MODULES
Definition: mod_common.c:543
#define CF_BUNDLE
Definition: cf3.defs.h:544
const PromiseTypeSyntax *const CF_ALL_PROMISE_TYPES[]
Definition: mod_common.c:524
SyntaxStatus
Definition: cf3.defs.h:637
@ SYNTAX_STATUS_NORMAL
Definition: cf3.defs.h:638
@ SYNTAX_STATUS_REMOVED
Definition: cf3.defs.h:640
@ SYNTAX_STATUS_DEPRECATED
Definition: cf3.defs.h:639
const PromiseTypeSyntax CF_COMMON_PROMISE_TYPES[]
Definition: mod_common.c:505
DataType
Definition: cf3.defs.h:368
@ CF_DATA_TYPE_CONTEXT_LIST
Definition: cf3.defs.h:380
@ CF_DATA_TYPE_CONTEXT
Definition: cf3.defs.h:379
@ CF_DATA_TYPE_OPTION_LIST
Definition: cf3.defs.h:376
@ CF_DATA_TYPE_BUNDLE
Definition: cf3.defs.h:378
@ CF_DATA_TYPE_NONE
Definition: cf3.defs.h:385
@ CF_DATA_TYPE_REAL
Definition: cf3.defs.h:371
@ CF_DATA_TYPE_STRING_LIST
Definition: cf3.defs.h:372
@ CF_DATA_TYPE_INT_LIST
Definition: cf3.defs.h:373
@ CF_DATA_TYPE_STRING
Definition: cf3.defs.h:369
@ CF_DATA_TYPE_INT
Definition: cf3.defs.h:370
@ CF_DATA_TYPE_BODY
Definition: cf3.defs.h:377
@ CF_DATA_TYPE_OPTION
Definition: cf3.defs.h:375
@ CF_DATA_TYPE_INT_RANGE
Definition: cf3.defs.h:381
@ CF_DATA_TYPE_CONTAINER
Definition: cf3.defs.h:384
@ CF_DATA_TYPE_REAL_RANGE
Definition: cf3.defs.h:382
@ CF_DATA_TYPE_REAL_LIST
Definition: cf3.defs.h:374
#define CF_INFINITY
Definition: cf3.defs.h:66
#define CF_LOWINIT
Definition: cf3.defs.h:552
#define CF_NOINT
Definition: cf3.defs.h:339
void yyerror(const char *str)
Definition: cf3parse.c:2924
void free(void *)
bool DoubleFromString(const char *s, double *value_out)
Definition: conversion.c:521
long IntFromString(const char *s)
Definition: conversion.c:390
const char * DataTypeToString(DataType type)
Definition: conversion.c:331
const void * EvalContextVariableGet(const EvalContext *ctx, const VarRef *ref, DataType *type_out)
const FnCallType CF_FNCALL_TYPES[]
bool IsNakedVar(const char *str, char vtype)
Definition: expand.c:1198
bool IsExpandable(const char *str)
Definition: expand.c:1117
const FnCallType * FnCallTypeGet(const char *name)
Definition: fncall.c:430
@ FNCALL_OPTION_COLLECTING
Definition: fncall.h:69
@ FNCALL_OPTION_CACHED
Definition: fncall.h:65
@ FNCALL_OPTION_VARARG
Definition: fncall.h:62
#define NULL
Definition: getopt1.c:56
int ListLen(const Item *list)
Definition: item_lib.c:450
Item * SplitString(const char *string, char sep)
Definition: item_lib.c:546
void DeleteItemList(Item *item)
Definition: item_lib.c:808
bool IsItemIn(const Item *list, const char *item)
Definition: item_lib.c:226
void JsonArrayAppendObject(JsonElement *const array, JsonElement *const object)
Append an object to an array.
Definition: json.c:1327
const char * JsonIteratorNextKey(JsonIterator *const iter)
Definition: json.c:557
JsonElement * JsonObjectCreate(const size_t initialCapacity)
Create a new JSON object.
Definition: json.c:880
JsonIterator JsonIteratorInit(const JsonElement *const container)
Definition: json.c:549
JsonElement * JsonObjectGet(const JsonElement *const object, const char *const key)
Definition: json.c:1266
void JsonObjectAppendBool(JsonElement *const object, const char *const key, const _Bool value)
Definition: json.c:1069
JsonElement * JsonArrayCreate(const size_t initialCapacity)
Create a new JSON array.
Definition: json.c:1281
void JsonArrayAppendString(JsonElement *const array, const char *const value)
Append a string to an array.
Definition: json.c:1287
JsonElement * JsonObjectGetAsArray(JsonElement *const object, const char *const key)
Get the value of a field in an object, as an array.
Definition: json.c:1245
void JsonObjectAppendString(JsonElement *const object, const char *const key, const char *const value)
Append a string field to an object.
Definition: json.c:1055
void JsonObjectAppendArray(JsonElement *const object, const char *const key, JsonElement *const array)
Append an array field to an object.
Definition: json.c:1089
JsonElement * JsonObjectGetAsObject(JsonElement *const object, const char *const key)
Get the value of a field in an object, as an object.
Definition: json.c:1224
void JsonObjectAppendObject(JsonElement *const object, const char *const key, JsonElement *const childObject)
Append an object field to an object.
Definition: json.c:1099
#define ProgrammingError(...)
Definition: misc_lib.h:33
const ConstraintSyntax CF_COMMON_XMLBODIES[]
Definition: mod_files.c:365
const ConstraintSyntax CF_COMMON_EDITBODIES[]
Definition: mod_files.c:137
bool ParseModeString(const char *modestring, mode_t *plusmask, mode_t *minusmask)
Definition: modes.c:51
bool StringMatchFull(const char *regex, const char *str)
Definition: regex.c:106
FnCall * RvalFnCallValue(Rval rval)
Definition: rlist.c:141
char * RvalScalarValue(Rval rval)
Definition: rlist.c:129
RvalType DataTypeToRvalType(DataType datatype)
Definition: rlist.c:44
size_t SeqLength(const Seq *seq)
Length of the sequence.
Definition: sequence.c:354
Seq * SeqNew(size_t initialCapacity, void(ItemDestroy)(void *item))
Definition: sequence.c:31
void SeqDestroy(Seq *seq)
Destroy an existing Sequence.
Definition: sequence.c:60
void SeqAppend(Seq *seq, void *item)
Append a new item to the Sequence.
Definition: sequence.c:104
static void * SeqAt(const Seq *seq, int i)
Definition: sequence.h:57
bool IsStrIn(const char *str, const char *const strs[])
Definition: string_lib.c:782
const char * body_type
Definition: cf3.defs.h:669
SyntaxStatus status
Definition: cf3.defs.h:672
const ConstraintSyntax * constraints
Definition: cf3.defs.h:670
Definition: buffer.h:50
const char * lval
Definition: cf3.defs.h:656
const char * validation_string
Definition: cf3.defs.h:660
const BodySyntax * body_type_syntax
Definition: cf3.defs.h:661
const DataType dtype
Definition: cf3.defs.h:657
SyntaxStatus status
Definition: cf3.defs.h:664
union ConstraintSyntax_::@11 range
const char * description
Definition: fncall.h:54
DataType dtype
Definition: fncall.h:53
const char * pattern
Definition: fncall.h:52
FnCallOption options
Definition: fncall.h:82
FnCallCategory category
Definition: fncall.h:83
SyntaxStatus status
Definition: fncall.h:84
const FnCallArg * args
Definition: fncall.h:79
const char * name
Definition: fncall.h:77
DataType dtype
Definition: fncall.h:78
Definition: item_lib.h:33
Item * next
Definition: item_lib.h:38
char * name
Definition: item_lib.h:34
SyntaxStatus status
Definition: cf3.defs.h:681
const char * bundle_type
Definition: cf3.defs.h:677
const ConstraintSyntax * constraints
Definition: cf3.defs.h:679
const char * promise_type
Definition: cf3.defs.h:678
Definition: rlist.h:35
Rval val
Definition: rlist.h:36
Rlist * next
Definition: rlist.h:37
Definition: cf3.defs.h:614
RvalType type
Definition: cf3.defs.h:616
void * item
Definition: cf3.defs.h:615
Sequence data-structure.
Definition: sequence.h:50
static JsonElement * BodyTypesToJson(void)
Definition: syntax.c:1158
static SyntaxTypeMatch CheckParseReal(const char *lv, const char *s, const char *range)
Definition: syntax.c:686
DataType StringDataType(EvalContext *ctx, const char *string)
Definition: syntax.c:426
const BodySyntax * BodySyntaxGet(const char *body_type)
Definition: syntax.c:149
const ConstraintSyntax * BodySyntaxGetConstraintSyntax(const ConstraintSyntax *body_syntax, const char *lval)
Definition: syntax.c:103
static SyntaxTypeMatch CheckParseString(const char *lv, const char *s, const char *range)
Definition: syntax.c:491
static const ConstraintSyntax * GetCommonConstraint(const char *lval)
Definition: syntax.c:85
static JsonElement * JsonBundleTypeNew(void)
Definition: syntax.c:1002
static JsonElement * ConstraintSyntaxToJson(const ConstraintSyntax *constraint_syntax)
Definition: syntax.c:961
static const char * FnCallCategoryToString(FnCallCategory category)
Definition: syntax.c:1212
static SyntaxTypeMatch CheckParseRealRange(const char *lval, const char *s, const char *range)
Definition: syntax.c:735
SyntaxTypeMatch CheckParseContext(const char *context, const char *range)
Definition: syntax.c:548
const PromiseTypeSyntax * PromiseTypeSyntaxGet(const char *bundle_type, const char *promise_type)
Definition: syntax.c:75
static JsonElement * PromiseTypesToJson(void)
Definition: syntax.c:1089
static JsonElement * BodySyntaxToJson(const BodySyntax *body_syntax)
Definition: syntax.c:977
static SyntaxTypeMatch CheckParseOpts(const char *s, const char *range)
Definition: syntax.c:801
JsonElement * SyntaxToJson(void)
Definition: syntax.c:1277
const char * SyntaxTypeMatchToString(SyntaxTypeMatch result)
Definition: syntax.c:262
static JsonElement * BundleTypesToJson(void)
Definition: syntax.c:1012
static SyntaxTypeMatch CheckFnCallType(const char *s, DataType dtype)
Definition: syntax.c:900
static SyntaxTypeMatch CheckParseInt(const char *lv, const char *s, const char *range)
Definition: syntax.c:566
DataType ExpectedDataType(const char *lvalname)
Definition: syntax.c:203
static const PromiseTypeSyntax * PromiseTypeSyntaxGetStrict(const char *bundle_type, const char *promise_type)
Definition: syntax.c:54
static SyntaxTypeMatch CheckParseIntRange(const char *lval, const char *s, const char *range)
Definition: syntax.c:620
static JsonElement * FunctionsToJson(void)
Definition: syntax.c:1258
bool CheckParseVariableName(const char *const name)
Definition: syntax.c:827
SyntaxTypeMatch CheckConstraintTypeMatch(const char *lval, Rval rval, DataType dt, const char *range, int level)
Definition: syntax.c:300
const ConstraintSyntax * PromiseTypeSyntaxGetConstraintSyntax(const PromiseTypeSyntax *promise_type_syntax, const char *lval)
Definition: syntax.c:115
const char * SyntaxStatusToString(SyntaxStatus status)
Definition: syntax.c:182
static JsonElement * FnCallTypeToJson(const FnCallType *fn_syntax)
Definition: syntax.c:1228
static JsonElement * JsonPromiseTypeNew(SyntaxStatus status)
Definition: syntax.c:1079
SyntaxTypeMatch
Definition: syntax.h:41
@ SYNTAX_TYPE_MATCH_ERROR_REAL_OUT_OF_RANGE
Definition: syntax.h:60
@ SYNTAX_TYPE_MATCH_ERROR_INT_PARSE
Definition: syntax.h:56
@ SYNTAX_TYPE_MATCH_ERROR_EMPTY_SCALAR_OUT_OF_RANGE
Definition: syntax.h:52
@ SYNTAX_TYPE_MATCH_ERROR_RANGE_BRACKETED
Definition: syntax.h:45
@ SYNTAX_TYPE_MATCH_ERROR_OPTS_OUT_OF_RANGE
Definition: syntax.h:62
@ SYNTAX_TYPE_MATCH_ERROR_STRING_UNIX_PERMISSION
Definition: syntax.h:54
@ SYNTAX_TYPE_MATCH_ERROR_UNEXPANDED
Definition: syntax.h:44
@ SYNTAX_TYPE_MATCH_ERROR_CONTEXT_OUT_OF_RANGE
Definition: syntax.h:67
@ SYNTAX_TYPE_MATCH_ERROR_SCALAR_OUT_OF_RANGE
Definition: syntax.h:51
@ SYNTAX_TYPE_MATCH_ERROR_INT_OUT_OF_RANGE
Definition: syntax.h:57
@ SYNTAX_TYPE_MATCH_ERROR_RANGE_MULTIPLE_ITEMS
Definition: syntax.h:46
@ SYNTAX_TYPE_MATCH_ERROR_FNCALL_UNKNOWN
Definition: syntax.h:65
@ SYNTAX_TYPE_MATCH_ERROR_GOT_LIST
Definition: syntax.h:48
@ SYNTAX_TYPE_MATCH_ERROR_GOT_SCALAR
Definition: syntax.h:47
@ SYNTAX_TYPE_MATCH_MAX
Definition: syntax.h:71
@ SYNTAX_TYPE_MATCH_ERROR_REAL_INF
Definition: syntax.h:59
@ SYNTAX_TYPE_MATCH_ERROR_ABSOLUTE_PATH
Definition: syntax.h:69
@ SYNTAX_TYPE_MATCH_ERROR_GOT_NULL
Definition: syntax.h:49
@ SYNTAX_TYPE_MATCH_OK
Definition: syntax.h:42
@ SYNTAX_TYPE_MATCH_ERROR_FNCALL_RETURN_TYPE
Definition: syntax.h:64
VarRef * VarRefParse(const char *var_ref_string)
void VarRefDestroy(VarRef *ref)
bool ExtractScalarReference(Buffer *out, const char *str, size_t len, bool extract_inner)
Definition: vars.c:379
bool IsCf3VarString(const char *str)
Definition: vars.c:123