title: K&R dcl program detects almost nothing
body: <p>I've been stuck with the dcl program from chapter 5.12 in K&amp;R C. It is basically a program which accepts a C variable/function/table declaration and prints a description of it in English. It works for simple declarations such as <code>int a</code> but fails with more complicated ones. For example, when I enter <code>int (*pf)()</code> I get the output</p>
  <pre><code>error: expected name or (dcl)
  Syntax error
  :  int
  error: expected name or (dcl)
  :  function that returns pf
  </code></pre>
  <p>Below is the portion of the code related to the program. The getch() and ungetch() functions are in a separate file.</p>
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;ctype.h&gt;
  #include &quot;getch.h&quot;
  
  #define MAXTOKEN 100
  
  enum { NAME, PARENS, BRACKETS };
  
  void dcl(void);
  void dirdcl(void);
  int gettoken(void);
  
  int tokentype;
  char token[MAXTOKEN];
  char name[MAXTOKEN];
  char datatype[MAXTOKEN];
  char out[1000];
  
  int main(void)
  {
      while (gettoken() != EOF) {
          strcpy(datatype, token);
          out[0] = '\0';
          dcl();
          if (tokentype != '\n')
              printf(&quot;Syntax error\n&quot;);
          printf(&quot;%s: %s %s\n&quot;, name, out, datatype);
      }
  
      return 0;
  }
  
  void dcl(void)
  {
      int ns;
      
      for (ns = 0; gettoken() == '*'; )
          ns++;
      dirdcl();
      while (ns-- &gt; 0)
          strcat(out, &quot; pointer to&quot;);
  }
  
  void dirdcl(void)
  {
      int type;
  
      if (tokentype == '(') {
          dcl();
          if (tokentype != ')')
              printf(&quot;error: missing )\n&quot;);
      } else if (tokentype == NAME)
          strcpy(name, token);
      else
          printf(&quot;error: expected name or (dcl)\n&quot;);
      while ((type=gettoken()) == PARENS || type == BRACKETS) {
          if (type == PARENS)
              strcat(out, &quot; function that returns&quot;);
          else {
              strcat(out, &quot; array&quot;);
              strcat(out, token);
              strcat(out, &quot; of&quot;);
          }
      }
  }
  
  int gettoken(void)
  {
      int c;
      char *p = token;
  
      while ((c = getch()) == ' ' || c == '\t')
          ;
      if (c == '(') {
          if ((c = getch()) == ')') {
              strcpy(token, &quot;()&quot;);
              return tokentype = PARENS;
          } else {
              ungetch(c);
              return tokentype = ')';
          }
      } else if (c == '[') {
          for (*p++ = c; (*p++ = getch()) != ']'; )
              ;
          *p = '\0';
          return tokentype = BRACKETS;
      } else if (isalpha(c)) {
          for (*p++ = c; isalnum(c = getch()); )
              *p++ = c;
          *p = '\0';
          ungetch(c);
          return tokentype = NAME;
      } else
          return tokentype = c;
  }
  </code></pre>
  <p>Could you please help me pinpoint the mistake?</p>