+void DeclareLocals (void)
+/* Declare local variables and types. */
+{
+ /* Remember the current stack pointer */
+ int InitialStack = StackPtr;
+
+ /* A place to store info about potential initializations of auto variables */
+ CollAppend (&CurrentFunc->LocalsBlockStack, 0);
+
+ /* Loop until we don't find any more variables */
+ while (1) {
+
+ /* Check variable declarations. We need to distinguish between a
+ ** default int type and the end of variable declarations. So we
+ ** will do the following: If there is no explicit storage class
+ ** specifier *and* no explicit type given, *and* no type qualifiers
+ ** have been read, it is assumed that we have reached the end of
+ ** declarations.
+ */
+ DeclSpec Spec;
+ ParseDeclSpec (&Spec, SC_AUTO, T_INT);
+ if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */
+ (Spec.Flags & DS_DEF_TYPE) != 0 && /* No type given */
+ GetQualifier (Spec.Type) == T_QUAL_NONE) { /* No type qualifier */
+ break;
+ }
+
+ /* Accept type only declarations */
+ if (CurTok.Tok == TOK_SEMI) {
+ /* Type declaration only */
+ CheckEmptyDecl (&Spec);
+ NextToken ();
+ continue;
+ }
+
+ /* Parse a comma separated variable list */
+ while (1) {
+
+ /* Parse one declaration */
+ ParseOneDecl (&Spec);
+
+ /* Check if there is more */
+ if (CurTok.Tok == TOK_COMMA) {
+ /* More to come */
+ NextToken ();
+ } else {
+ /* Done */
+ break;
+ }
+ }
+
+ /* A semicolon must follow */
+ ConsumeSemi ();
+ }
+
+ /* Be sure to allocate any reserved space for locals */
+ F_AllocLocalSpace (CurrentFunc);
+
+ /* No auto variables were inited. No new block on the stack then. */
+ if (CollLast (&CurrentFunc->LocalsBlockStack) == NULL) {
+ CollPop (&CurrentFunc->LocalsBlockStack);
+ }
+
+ /* In case we've allocated local variables in this block, emit a call to
+ ** the stack checking routine if stack checks are enabled.
+ */
+ if (IS_Get (&CheckStack) && InitialStack != StackPtr) {
+ g_cstackcheck ();
+ }
+}