# empty --- parse an empty production, since stacc can't handle it

   subroutine empty (state)
   integer state

   state = ACCEPT

   return
   end



# type_or_sc_spec --- accept a type or storage class specifier

   subroutine type_or_sc_spec (state)
   integer state

   include "c1_com.r.i"

   integer findsym

   select (Symbol)
      when (AUTOSYM,
            CHARSYM,
            DOUBLESYM,
            ENUMSYM,
            EXTERNSYM,
            FLOATSYM,
            INTSYM,
            LONGSYM,
            REGISTERSYM,
            SHORTSYM,
            STATICSYM,
            STRUCTSYM,
            TYPEDEFSYM,
            UNIONSYM,
            UNSIGNEDSYM)
         state = ACCEPT
   else if (Symbol == IDSYM
                  && findsym (Symtext, Symptr, IDCLASS) == YES
                  && SYMSC (Symptr) == TYPEDEF_SC)
      state = ACCEPT
   else
      state = NOMATCH

   return
   end



# not_statement_start --- does the current token not begin a statement

   subroutine not_statement_start (state)
   integer state

   include "c1_com.r.i"

   integer findsym

   select (Symbol)
      when (IFSYM,
            WHILESYM,
            DOSYM,
            FORSYM,
            SWITCHSYM,
            CASESYM,
            DEFAULTSYM,
            BREAKSYM,
            CONTINUESYM,
            RETURNSYM,
            GOTOSYM,
            '('c,
            '{'c,
            '*'c,
            '&'c,
            '-'c,
            '+'c,
            '!'c,
            DECSYM,
            INCSYM,
            '~'c,
            '}'c,
            EOF)
         state = NOMATCH
   else if (Symbol == IDSYM) {
      if (findsym (Symtext, Symptr, IDCLASS) == YES
               && SYMSC (Symptr) == TYPEDEF_SC)
         state = ACCEPT
      else
         state = NOMATCH
      }
   else
      state = ACCEPT

   return
   end



# not_statement_end --- does the current symbol end a compound statement

   subroutine not_statement_end (state)
   integer state

   include "c1_com.r.i"

   if (Symbol == '}'c || Symbol == EOF)
      state = NOMATCH
   else
      state = ACCEPT

   return
   end



# initializer --- parse and generate code for an initializer

   subroutine initializer (state)
   integer state

   include "c1_com.r.i"

   integer bc, rc, sflag
   integer is_stored
   pointer id

   id = SS (1)
   if (SYMSC (id) == STATIC_SC || SYMSC (id) == EXTERN_SC
         || SYMSC (id) == DEFAULT_SC && SYMLL (id) == 1)
      sflag = YES # Only constant and "&object" initializers allowed
   else
      sflag = NO

   bc = 0
   rc = 0

   if (is_stored (id) == NO) {
      ERROR_SYMBOL (Mem (SYMTEXT (id)))
      SYNERR ("Identifier cannot be initalized"p)
      }

   call out_initstart
   call initr (SYMMODE (id), bc, rc, sflag) # The mode pointer may be changed
   call out_initend

    ### The ending NULL for the INIT list must be supplied by the caller

   state = ACCEPT
   return
   end




# initr --- recursively generate code for an initializer

   subroutine initr (mode, bc, rc, sflag)
   pointer mode
   integer bc, rc, sflag

   include "c1_com.r.i"

   integer state, ldiff
   integer wsize
   pointer t
   longint sizeof_mode

   rc += 1
   if (MODETYPE (mode) == ARRAY_MODE) {

      if (Symbol == '{'c) {
         call getsym
         bc += 1
         call array_init (mode, bc, rc, sflag)
         if (Symbol ~= '}'c)
            SYNERR ("Right brace required"p)
         else
            call getsym
         bc -= 1
         }
      else
         call array_init (mode, bc, rc, sflag)
      }

   else if (MODETYPE (mode) == STRUCT_MODE) {


      if (Symbol == '{'c) {
         call getsym
         bc += 1
         call struct_init (mode, bc, rc, sflag)
         if (Symbol ~= '}'c)
            SYNERR ("Right brace required"p)
         else
            call getsym
         bc -= 1
         }
      else
         call struct_init (mode, bc, rc, sflag)
      }

   else if (MODETYPE (mode) == UNION_MODE) {
      t = MODESMLIST (mode)
      if (t == LAMBDA)
         SYNERR ("Can't initialize union with no members"p)
      else {
         call initr (SYMMODE (SMSYM (t)), bc, rc, sflag)
         ldiff = wsize (sizeof_mode (mode)) _
                     - wsize (sizeof_mode (SYMMODE (SMSYM (t))))
         while (ldiff > 0)
            {
            call gen_lit (SHORTLITSYM, "0"s, 0)
            call out_init (Short_mode_ptr)
            ldiff -= 1
            }
         }
      }

   else if (MODETYPE (mode) == FIELD_MODE)
      SYNERR ("Fields cannot be initialized"p)
   else if (MODETYPE (mode) == FUNCTION_MODE)
      SYNERR ("Functions cannot be initialized"p)

   else {

      if (Symbol == '{'c) {
         call getsym
         bc += 1
         call scalar_init (mode, bc, rc, sflag)
         if (Symbol ~= '}'c)
            SYNERR ("Right brace required"p)
         else
            call getsym
         bc -= 1
         }
      else
         call scalar_init (mode, bc, rc, sflag)
      }

   if (Symbol == ','c && bc > 0)
      call getsym

   rc -= 1
   return
   end



# scalar_init --- generate code to initialize a scalar

   subroutine scalar_init (mode, bc, rc, sflag)
   pointer mode
   integer bc, rc, sflag

   include "c1_com.r.i"

   integer state, p
   integer is_constant

   if (Symbol == '}'c)
      call gen_lit (SHORTLITSYM, "0"s, 0)
   else {
      call expr0 (state)
      if (state ~= ACCEPT
         || Symbol ~= ','c && Symbol ~= '}'c && Symbol ~= ';'c)
         SYNERR ("Illegal token in initializer"p)
      if (state ~= ACCEPT)       # error recovery
         call gen_lit (SHORTLITSYM, "0"s, 0)
      }

   call gen_make_arith
   call gen_convert (mode)
   if (sflag == YES) {  # Static initializer restrictions
      call es_top (p)
      # CONVERT_OP of an array or function resulting in an integer
      # acts like a REFTO_OP.
      while (SYMTYPE (p) == EXPSYMTYPE && EXPOP (p) == CONVERT_OP
            && (MODETYPE (SYMMODE (p)) ~= POINTER_MODE
               || (MODETYPE (SYMMODE (EXPLEFT (p))) ~= ARRAY_MODE
                  && MODETYPE (SYMMODE (EXPLEFT (p))) ~= FUNCTION_MODE)
               ))
         p = EXPLEFT (p)
      if (is_constant (p) == NO)
         if (SYMTYPE (p) == EXPSYMTYPE && EXPOP (p) == CONVERT_OP
               && MODETYPE (SYMMODE (p)) == POINTER_MODE
               && (MODETYPE (SYMMODE (EXPLEFT (p))) == ARRAY_MODE
                  || MODETYPE (SYMMODE (EXPLEFT (p))) == FUNCTION_MODE)
               && (SYMTYPE (EXPLEFT (p)) == IDSYMTYPE
                  || SYMTYPE (EXPLEFT (p)) == LITSYMTYPE)
               )
            ;  # It's a CONVERT_OP in a REFTO_OP's guise (see above)
         else if (SYMTYPE (p) ~= EXPSYMTYPE || EXPOP (p) ~= REFTO_OP
               || (SYMTYPE (EXPLEFT (p)) ~= IDSYMTYPE
                     && SYMTYPE (EXPLEFT (p)) ~= LITSYMTYPE))
            SYNERR ("SEG only allows '&object' and const exprs as static inits"p)
      }
   call out_init (mode)

   return
   end




# array_init --- generate code to initialize an array

   subroutine array_init (mode, bc, rc, sflag)
   pointer mode
   integer bc, rc, sflag

   include "c1_com.r.i"

   pointer p, q
   integer ic, llen, flen, i
   integer ctop, ctoc, wsize
   character cbuf (MAXTOK)
   longint ml
   longint sizeof_mode, get_long

#  Warning:  'array_init' must modify the 'mode' pointer it is
#            passed to fill in unspecified array dimensions (mode
#            table entries themselves cannot be modified).  However,
#            if it changes the pointer when 'initr' and 'initializer'
#            are not its immediate callers, the mode table will get
#            screwed up (because by definition, another mode entry
#            parent pointer, not a symbol's pointer, is being passed).
#            The value 'rc' (recursion count) will be 1 if and only
#            'mode' can be changed.

   ml = get_long (MODELEN (mode))

   if (ml == 0 && rc > 1)
      SYNERR ("Only the first array bound may be omitted"p)

   p = MODEPARENT (mode)
   if ((MODETYPE (p) == CHAR_MODE || MODETYPE (p) == INT_MODE
          || MODETYPE (p) == CHAR_UNS_MODE || MODETYPE (p) == SHORT_UNS_MODE
          || MODETYPE (p) == SHORT_MODE || MODETYPE (p) == UNSIGNED_MODE)
      && (Symbol == CHARLITSYM && Symlen > 1 || Symbol == STRLITSYM)) {

      call gen_lit (Symbol, Symtext, Symlen)
      call es_top (q)
      llen = wsize (sizeof_mode (SYMMODE (q)))

      if (ml == 0 && rc <= 1) {
         mode = MODEPARENT (mode)
         call create_mode (mode, ARRAY_MODE, llen)
         }
      else if (ml < llen)
         SYNERR ("String constant too large for array"p)

      call out_init (mode)

      flen = wsize (sizeof_mode (mode))
      while (flen > llen) {         # In case the literal is too short
         call gen_lit (SHORTLITSYM, "0"s, 0)
         call out_init (Short_mode_ptr)
         llen += wsize (sizeof_mode (Short_mode_ptr))
         }
      call getsym
      }

   else {
      for (ic = 0; ic < ml || ml == 0
                    && Symbol ~= '}'c && Symbol ~= ';'c; ic += 1)
         call initr (MODEPARENT (mode), bc, rc, sflag)
      if (ml == 0 && rc <= 1) {
         mode = MODEPARENT (mode)
         call create_mode (mode, ARRAY_MODE, ic)
         }
      }

   return
   end




# struct_init --- generate code to initialize a structure

   subroutine struct_init (mode, bc, rc, sflag)
   pointer mode
   integer bc, rc, sflag

   include "c1_com.r.i"

   pointer t

   for (t = MODESMLIST (mode); t ~= LAMBDA; t = SMSIBLING (t))
      call initr (SYMMODE (SMSYM (t)), bc, rc, sflag)  #  check this !!

   return
   end



# next_is_type --- the "next" symbol is a type name

   integer function next_is_type (d)
   integer d

   include "c1_com.r.i"

   integer findsym

   select (Nsymbol)
      when (CHARSYM,
            DOUBLESYM,
            ENUMSYM,
            FLOATSYM,
            INTSYM,
            LONGSYM,
            SHORTSYM,
            STRUCTSYM,
            UNIONSYM,
            UNSIGNEDSYM)
         return (YES)
   else if (Nsymbol == IDSYM
                  && findsym (Nsymtext, Nsymptr, IDCLASS) == YES
                  && SYMSC (Nsymptr) == TYPEDEF_SC)
      return (YES)

   return (NO)
   end
