Cetus' internal parser was developed based on the ANSI C (c89) grammar that is distributed with the Antlr package. Since its initial development, the parser has changed gradually to accomodate modern C features, but it still has limitation of not handling c99 features. The following examples summarize the features that are not handled by the Cetus compiler.
// Example of restrict qualifiers void foo(int n, int * restrict p, int * restrict q) { while (n-- > 0) { *p++ = *q++; } }
The keyword restrict is used to declare a restricted pointer. The program is expected to have an exclusive access to a memory region through the restricted pointer. Cetus' parser just breaks when it see this keyword.
// static and type qualifiers in parameter array declarations void foo(int arr[static 10]); /* arr points to the first of at least 10 ints */ void foo(int arr[const 10]); /* arr is a const pointer */ void foo(int arr[static const i]); /* arr points to at least i ints; i is computed at run time. */ void foo(int arr[const static i]); /* alternate syntax to previous example */ void foo(int arr[const]); /* const pointer to int */
Static and type qualifiers were used to describe the specified behavior on an array parameters. Cetus' parser breaks when it see these syntax.
// extended identifiers with universal character name int abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz; int aaaa\u03c0; int bbbb\U01f1ffa0;
The first example shows a long identifier which is supported by Cetus. Length-wise, c99 sets lower bounds on identifiers -- 31 for external linkage and 63 for others. The next two examples are extended identifiers that contain universal character names, which are not supported by Cetus.
// hexadecimal floating constants #includeint main (void) { double d = 0x0.3p10; printf ("%.f\n", d); return 0; }
Cetus' parser breaks when it sees a hexadecimal floating constants. According to the c99 grammar, the constant 0x0.3p10 is parsed as 0x (hexadecimal-prefix), 0.3(hexadecimal-fractional-constant), and p10(binary-exponent-part).
// compound literals struct st {int a; char b[2];}; struct st st0 = (struct st) {1, 'a', 'b'}; char **foo = (char *[]) {"x", "y", "z"};
Compound literals are used to assign multiple scalar values to a portion of aggregate objects and takes the above form which consists of a type cast and a compounded literals. Cetus' parser does not break with this code but it loses the literals in the curly braces.
// designated initializers for array elements #includeint main(void) { int a[5] = { [0] = 1, [4] = 2 }; int i; printf("The array is \n"); for (i = 0; i < 5; i++) { printf("%d\n", a[i]); } return 0; }
Designated initializers are used to initialize parts of aggregate objects such as arrays and structrues. The above example initializes only two elements of the array a after declaring it. Cetus' parser does not break with this code but it loses the initialization part.
// mix of declarations and executable code #includeint main(void) { int x = 1; printf("x is %d\n", x); int y = 2; printf("y is %d\n", y); return 0; }
Cetus' parser breaks when it sees a variable declaration not placed in the header part of a block scope as in the above example. This feature may be the most frequently used c99 feature, and many Cetus users actually ask questions about parsing issue with this type of code.
// declaration of a variable in a for statement header #includeint main(void) { printf("Values of x\n"); for (int x = 1; x <= 5; x++) { printf("%d\n", x); } return 0; }
Another c99 feature that may be used frequently by code writers who are accustomed to C++/JAVA coding. Cetus' parser breaks when it sees a variable declaration within the for statement header.