ch5-declare (Decode, describe declarations)

Chapter_5     Exercise_5-17     Index_program undeclare     Exercise_5-18







CONTENTS:     dcl.txt     dcl.c     undcl.txt     description.txt




dcl.txt     K&R, p. 122-123         download


int *pf()
int (*pf)()
char (*apf[])()
char **argv
int (*daytab)[13]
int *daytab[13]
void *comp()
void (*comp)()
char (*(*x())[])()
char (*(*x[3])())[5]





dcl.c     K&R, p. 122-125         download


#include <stdio.h> // for printf(), getchar(), EOF
#include <string.h> // for strcat(), strcpy()
#include <ctype.h> // for isalpha(), isalnum()

/*
dcl: optional *s direct-dcl
direct-dcl: name
(dcl)
direct-dcl()
direct-dcl[optional size]
*/

#define FALSE 0
#define TRUE 1

#define MAXTOKEN 100 // max token length
#define MAXOUTPUT 1000 // max length of output string

enum {NAME, PARENS, BRACKETS};

void dcl(void); // parse a declarator
void dirdcl(void); // parse a direct declarator

int gettoken(void);

int VERBOSE = FALSE;
int tokentype; // type of last token
char token[MAXTOKEN]; // last token string
char name[MAXTOKEN]; // identifier name
char datatype[MAXTOKEN]; // data type: char, int, etc.
char out[MAXOUTPUT]; // output string

int main(int argc, char *argv[]) // convert declaration to words
{
int c;

while (--argc > 0 && (*++argv)[0] == '-') // optional argument
{
while (c = *++argv[0]) // -v, -vv, -v -vv, etc.
{
switch(c)
{
case 'v' :
VERBOSE = TRUE;
break;
default:
printf("Illegal option: '%c'\n", c);
printf("Usage: ./dcl [-v]\n");
printf("-v - verbose\n");
return 1; // exit main(), signalling error
}
}
}

if (argc) // if (argc > 0)
{
printf("Usage: ./dcl [-v]\n");
printf("-v - verbose\n");
return 1; // end program, signalling error
}

while(gettoken() != EOF)
{ // first token on each line is the data type
strcpy(datatype, token);

out[0] = '\0'; // (re)set

dcl(); // parse rest of line

if (tokentype != '\n')
{printf("Syntax error\n");}

printf("%s%s%s %s\n", name, (VERBOSE) ? ": " : "", out, datatype);
}

return 0;
}

void dcl(void) // parse a declarator
{
int ns; // no of stars

for (ns = 0; gettoken() == '*'; ) // count *s
{ns++;}

dirdcl(); // recursive-descent call

while (ns-- > 0)
{
if (VERBOSE)
{strcat(out, " pointer to");}
else {strcat(out, " *");}
}
}

void dirdcl(void) // parse a direct declarator
{
int type;

if (tokentype == '(') // (dcl)
{
dcl(); // recursive-descent call

if (tokentype != ')')
{printf("Error: missing ')'\n");}
}
else if (tokentype == NAME)
{strcpy(name, token);}
else
{printf("Error: expected name or (dcl)\n");}

while((type = gettoken()) == PARENS || type == BRACKETS)
{ // last token should be '\n' or EOF
if (type == PARENS)
{
if (VERBOSE)
{strcat(out, " function returning");}
else{strcat(out, " ()");}
}
else // BRACKETS
{
if (VERBOSE)
{
strcat(out, " array");
strcat(out, token); // token holds [...]
strcat(out, " of");
}
else
{
strcat(out, " ");
strcat(out, token); // token holds [...]
}
}
}
}

int getch(void);
void ungetch(int);

int gettoken(void)
{
int c;
char *p = token;

while((c = getch()) == ' ' || c == '\t')
{} // skip beginning whitespace

if (c == '(')
{
if ((c = getch()) == ')')
{
strcpy(token, "()");
return tokentype = PARENS;
}
else
{
ungetch(c);
return tokentype = '(';
}
}
else if (c == '[')
{
for (*p++ = c; (*p++ = getch()) != ']'; )
{} // token holds [...]
*p = '\0'; // end string
return tokentype = BRACKETS;
}
else if (isalpha(c))
{
for (*p++ = c; isalnum(c = getch()); )
{*p++ = c;}
*p = '\0'; // end string
ungetch(c);
return tokentype = NAME;
}
else {return tokentype = c;} // could be ')' or '\n' or EOF
}

// buffer for ungetch():
int buf = EOF-1; // not a real character, not even EOF

int getch(void) // get a (possibly pushed-back) character
{
if (buf < EOF)
{
return getchar();
}

int temp = buf; // buf >= EOF
buf = EOF-1; // reset buf

return temp;
}
// push character back on input (make it available for the next getch()):
void ungetch(int c)
{
buf = c;
}
/*
gcc dcl.c -o dcl
./dcl v
Usage: ./dcl [-v]
-v - verbose

./dcl -w
Illegal option: 'w'
Usage: ./dcl [-v]
-v - verbose

./dcl // Enter (input from keyboard)
char (*apf[])() // Enter
apf[] * () char
char **argv // Enter
argv * * char
int (*daytab)[13] // Enter
daytab * [13] int
int *daytab[13] // Enter
daytab [13] * int
// Ctrl^D in Linux, Ctrl^Z+Enter in Windows (EOF)

./dcl -v // Enter (input from keyboard)
char (*apf[])() // Enter
apf: array[] of pointer to function returning char
char **argv // Enter
argv: pointer to pointer to char
int (*daytab)[13] // Enter
daytab: pointer to array[13] of int
int *daytab[13] // Enter
daytab: array[13] of pointer to int
// Ctrl^D in Linux, Ctrl^Z+Enter in Windows (EOF)

./dcl < dcl.txt > "undcl(copy).txt"
diff -s undcl.txt "undcl(copy).txt"
// Files undcl.txt and undcl(copy).txt are identical
meld undcl.txt "undcl(copy).txt"
// Files are identical

./dcl -v < dcl.txt > "description(copy).txt"
diff -s description.txt "description(copy).txt"
// Files description.txt and description(copy).txt are identical
meld description.txt "description(copy).txt"
// Files are identical
*/





Notes:  [-v] signals an optional -v argument.
File names "undcl(copy).txt" and "description(copy).txt" are within quotes because the shell interprets parentheses (subshell).











undcl.txt     K&R, p. 122-123, 126         download


pf () * int
pf * () int
apf [] * () char
argv * * char
daytab * [13] int
daytab [13] * int
comp () * void
comp * () void
x () * [] * () char
x [3] * () * [5] char





description.txt     K&R, p. 122-123         download


pf:  function returning pointer to int
pf:  pointer to function returning int
apf:  array[] of pointer to function returning char
argv:  pointer to pointer to char
daytab:  pointer to array[13] of int
daytab:  array[13] of pointer to int
comp:  function returning pointer to void
comp:  pointer to function returning void
x:  function returning pointer to array[] of pointer to function returning char
x:  array[3] of pointer to function returning pointer to array[5] of char









Chapter_5     Exercise_5-17     Index_program BACK_TO_TOP undeclare     Exercise_5-18



Comments

Popular posts from this blog

Contents

Blogger Page Margins in Contempo