V10/cmd/asd/path.c
/*
* getpath (file) - read a path name
* putpath (file, path) - write a path name
*
* These subroutines cater to the possibility of unprintable
* characters in the path names being read or written, by
* using the same sort of \ conventions commonly found in
* C character constants. The result of getpath is a pointer
* to a static buffer whose contents will stay around no longer
* than the next call to getpath. When getpath is called, the
* character about to be read from the input file must be the
* first character of the path name.
*
* There are a few problems, mostly relating to bugs and language
* changes, to watch out for in these routines. First of all,
* we assume that \v is known by the C compiler, even though
* it is not mentioned in Kernighan and Ritchie. The reason for
* this is that if we do not make this assumption, we run into
* a common bug in the handling of iscntrl(). Although the
* manuals all say that if c is a white-space character that is
* not a blank, then iscntrl(c) is true, several versions of the
* C library disagree with the documentation. Thus we try to
* list all the white-space characters explicitly.
*/
#include <stdio.h>
#include <ctype.h>
#include "asd.h"
#define CHUNK 64
static char *r;
static unsigned size;
char *
getpath (file)
register FILE *file;
{
register int c;
register int len = 0;
c = getc (file);
while (!isspace(c) && c != EOF) {
register int i = 0, n = 0;
/* determine the next input character */
if (c == '\\') {
c = getc (file);
switch (c) {
case '\\':
break;
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 't':
c = '\t';
break;
case 'b':
c = '\b';
break;
case 'f':
c = '\f';
break;
case 'v':
c = '\v';
break;
case ' ':
/* c = ' '; */
break;
default:
while (c >= '0' && c <= '7' && i < 3) {
n = (n << 3) + c - '0';
i++;
c = getc (file);
}
ungetc (c, file);
c = n;
break;
}
}
/* ensure there's room in the buffer */
if (len >= size)
r = ralloc (r, size += CHUNK);
/* put the character in the buffer */
r[len++] = c;
/* read the next character */
c = getc (file);
}
/* unless we hit eof, we read one character too far. */
if (c != EOF)
ungetc (c, file);
/* put a final null into the buffer */
if (len >= size)
r = ralloc (r, size += CHUNK);
r[len] = '\0';
return r;
}
void
putpath (file, path)
register FILE *file;
char *path;
{
register char *p = path;
register int c;
while ((c = *p++) != NULL) {
switch (c) {
case '\n':
fprintf (file, "\\n");
break;
case '\r':
fprintf (file, "\\r");
break;
case '\b':
fprintf (file, "\\b");
break;
case '\t':
fprintf (file, "\\t");
break;
case '\f':
fprintf (file, "\\f");
break;
case '\v':
fprintf (file, "\\v");
break;
case '\\':
fprintf (file, "\\\\");
break;
case ' ':
fprintf (file, "\\ ");
break;
default:
if (iscntrl (c))
fprintf (file,
*p >= '0' && *p <= '7'? "\\%.3o": "\\%o",
c);
else
putc (c, file);
break;
}
}
}