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
Post a Comment