/* VMS-specific definitions */
#ifdef VMS
#include <descrip.h>
-#define O_RDONLY 0 /* Open arg for Read/Only */
-#define O_WRONLY 1 /* Open arg for Write/Only */
-#define read(fd,buf,size) VMS_read (fd,buf,size)
-#define write(fd,buf,size) VMS_write (fd,buf,size)
#define open(fname,mode,prot) VMS_open (fname,mode,prot)
#define fopen(fname,mode) VMS_fopen (fname,mode)
#define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
#define fstat(fd,stbuf) VMS_fstat (fd,stbuf)
static int VMS_fstat (), VMS_stat ();
-static int VMS_read ();
-static int VMS_write ();
static int VMS_open ();
static FILE * VMS_fopen ();
static FILE * VMS_freopen ();
#define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
#define INO_T_HASH(a) 0
#define INCLUDE_LEN_FUDGE 12 /* leave room for VMS syntax conversion */
-#ifdef __GNUC__
-#define BSTRING /* VMS/GCC supplies the bstring routines */
-#endif /* __GNUC__ */
#endif /* VMS */
+/* Windows does not natively support inodes, and neither does MSDOS. */
+#if (defined (_WIN32) && ! defined (CYGWIN32)) || defined (__MSDOS__)
+#define INO_T_EQ(a, b) 0
+#endif
+
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
#ifndef VMS
#ifndef HAVE_STRERROR
extern int sys_nerr;
-#if defined(bsd4_4)
-extern const char *const sys_errlist[];
-#else
extern char *sys_errlist[];
-#endif
#else /* HAVE_STRERROR */
char *strerror ();
#endif
static int warn_trigraphs;
+/* Nonzero means warn if undefined identifiers are evaluated in an #if. */
+
+int warn_undef;
+
/* Nonzero means warn if #import is used. */
static int warn_import = 1;
int traditional;
+/* Nonzero for the 1989 C Standard, including corrigenda and amendments. */
+
+int c89;
+
/* Nonzero causes output not to be done,
but directives such as #define that have side effects
are still obeyed. */
/* table to tell if char can be first char of a c identifier. */
U_CHAR is_idstart[256];
/* table to tell if c is horizontal space. */
-U_CHAR is_hor_space[256];
+static U_CHAR is_hor_space[256];
/* table to tell if c is horizontal or vertical space. */
-static U_CHAR is_space[256];
+U_CHAR is_space[256];
/* names of some characters */
static char *char_name[256];
static char *savestring PROTO((char *));
\f
/* Read LEN bytes at PTR from descriptor DESC, for file FILENAME,
- retrying if necessary. Return a negative value if an error occurs,
+ retrying if necessary. If MAX_READ_LEN is defined, read at most
+ that bytes at a time. Return a negative value if an error occurs,
otherwise return the actual number of bytes read,
which must be LEN unless end-of-file was reached. */
char *ptr;
int len;
{
- int left = len;
+ int left, rcount, nchars;
+
+ left = len;
while (left > 0) {
- int nchars = read (desc, ptr, left);
+ rcount = left;
+#ifdef MAX_READ_LEN
+ if (rcount > MAX_READ_LEN)
+ rcount = MAX_READ_LEN;
+#endif
+ nchars = read (desc, ptr, rcount);
if (nchars < 0)
{
#ifdef EINTR
}
/* Write LEN bytes at PTR to descriptor DESC,
- retrying if necessary, and treating any real error as fatal. */
+ retrying if necessary, and treating any real error as fatal.
+ If MAX_WRITE_LEN is defined, write at most that many bytes at a time. */
static void
safe_write (desc, ptr, len)
char *ptr;
int len;
{
+ int wcount, written;
+
while (len > 0) {
- int written = write (desc, ptr, len);
+ wcount = len;
+#ifdef MAX_WRITE_LEN
+ if (wcount > MAX_WRITE_LEN)
+ wcount = MAX_WRITE_LEN;
+#endif
+ written = write (desc, ptr, wcount);
if (written < 0)
{
#ifdef EINTR
if (i + 1 == argc)
fatal ("Filename missing after -pcp option");
pcp_fname = argv[++i];
- pcp_outfile =
- ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
- ? fopen (pcp_fname, "w")
- : stdout);
+ pcp_outfile
+ = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
+ ? fopen (pcp_fname, "w")
+ : stdout);
if (pcp_outfile == 0)
pfatal_with_name (pcp_fname);
no_precomp = 1;
case 'l':
if (! strcmp (argv[i], "-lang-c"))
- cplusplus = 0, cplusplus_comments = 1, objc = 0;
+ cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 0;
if (! strcmp (argv[i], "-lang-c89"))
- cplusplus = 0, cplusplus_comments = 0, objc = 0;
+ cplusplus = 0, cplusplus_comments = 0, c89 = 1, objc = 0;
if (! strcmp (argv[i], "-lang-c++"))
- cplusplus = 1, cplusplus_comments = 1, objc = 0;
+ cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 0;
if (! strcmp (argv[i], "-lang-objc"))
- objc = 1, cplusplus = 0, cplusplus_comments = 1;
+ cplusplus = 0, cplusplus_comments = 1, c89 = 0, objc = 1;
if (! strcmp (argv[i], "-lang-objc++"))
- objc = 1, cplusplus = 1, cplusplus_comments = 1;
+ cplusplus = 1, cplusplus_comments = 1, c89 = 0, objc = 1;
if (! strcmp (argv[i], "-lang-asm"))
lang_asm = 1;
if (! strcmp (argv[i], "-lint"))
warn_stringify = 1;
else if (!strcmp (argv[i], "-Wno-traditional"))
warn_stringify = 0;
+ else if (!strcmp (argv[i], "-Wundef"))
+ warn_undef = 1;
+ else if (!strcmp (argv[i], "-Wno-undef"))
+ warn_undef = 0;
else if (!strcmp (argv[i], "-Wimport"))
warn_import = 1;
else if (!strcmp (argv[i], "-Wno-import"))
/* A single quoted string is treated like a double -- some
programs (e.g., troff) are perverse this way */
- if (ident_length)
+ /* Handle any pending identifier;
+ but the L in L'...' or L"..." is not an identifier. */
+ if (ident_length
+ && ! (ident_length == 1 && hash == HASHSTEP (0, 'L')))
goto specialchar;
start_line = ip->lineno;
}
*obp++ = c;
/* A sign can be part of a preprocessing number
- if it follows an e. */
- if (c == 'e' || c == 'E') {
+ if it follows an `e' or `p'. */
+ if (c == 'e' || c == 'E' || c == 'p' || c == 'P') {
while (ibp[0] == '\\' && ibp[1] == '\n') {
++ip->lineno;
ibp += 2;
}
if (*ibp == '+' || *ibp == '-') {
*obp++ = *ibp++;
- /* But traditional C does not let the token go past the sign. */
- if (traditional)
+ /* But traditional C does not let the token go past the sign,
+ and C89 does not allow `p'. */
+ if (traditional || (c89 && (c == 'p' || c == 'P')))
break;
}
}
if (!traditional && obp != op->buf) {
switch (obp[-1]) {
case '!': case '%': case '&': case '*':
- case '+': case '-': case '/': case ':':
- case '<': case '=': case '>': case '^':
- case '|':
+ case '+': case '-': case '.': case '/':
+ case ':': case '<': case '=': case '>':
+ case '^': case '|':
/* If we are expanding a macro arg, make a newline marker
to separate the tokens. If we are making real output,
a plain space will do. */
obuf.length = length * 2 + 100; /* Usually enough. Why be stingy? */
obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length);
+ obuf.nominal_fname = 0;
+ obuf.inc = 0;
+ obuf.dir = 0;
obuf.fname = 0;
obuf.macro = 0;
+ obuf.if_stack = 0;
obuf.free_ptr = 0;
+ obuf.system_header_p = 0;
CHECK_DEPTH ({return obuf;});
if (!is_idstart[*ip->bufp])
goto oops;
+ if (ip->bufp[0] == 'L' && (ip->bufp[1] == '\'' || ip->bufp[1] == '"'))
+ goto oops;
if ((hp = lookup (ip->bufp, -1, -1))) {
if (pcp_outfile && pcp_inside_if
&& (hp->type == T_CONST
int retried = 0; /* Have already tried macro
expanding the include line*/
int angle_brackets = 0; /* 0 for "...", 1 for <...> */
+#ifdef VMS
+ int vaxc_include = 0; /* 1 for token without punctuation */
+#endif
int pcf = -1;
char *pcfbuf;
char *pcfbuflimit;
int pcfnum;
+ if (pedantic && !instack[indepth].system_header_p)
+ {
+ if (importing)
+ pedwarn ("ANSI C does not allow `#import'");
+ if (skip_dirs)
+ pedwarn ("ANSI C does not allow `#include_next'");
+ }
+
if (importing && warn_import && !inhibit_warnings
&& !instack[indepth].system_header_p && !import_warning) {
import_warning = 1;
while (fin != limit && (!isspace(*fin)))
*fend++ = *fin++;
warning ("VAX-C-style include specification found, use '#include <filename.h>' !");
+ vaxc_include = 1;
if (fin == limit) {
angle_brackets = 1;
/* If -I-, start with the first -I dir after the -I-. */
full VMS file specification */
if (searchptr->fname[0]) {
/* Fix up the filename */
- hack_vms_include_specification (fname);
+ hack_vms_include_specification (fname, vaxc_include);
} else {
- /* This is a normal VMS filespec, so use it unchanged. */
+ /* This is a normal VMS filespec, so use it unchanged. */
strcpy (fname, fbeg);
/* if it's '#include filename', add the missing .h */
- if (index(fname,'.')==NULL) {
+ if (vaxc_include && index(fname,'.')==NULL) {
strcat (fname, ".h");
}
}
while (is_idchar[*bp]) {
bp++;
/* do we have a "special" rest-args extension here? */
- if (limit - bp > REST_EXTENSION_LENGTH &&
- bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
+ if (limit - bp > REST_EXTENSION_LENGTH
+ && bcmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
rest_args = 1;
temp->rest_args = 1;
break;
struct arglist *otemp;
for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
- if (temp->length == otemp->length &&
- bcmp (temp->name, otemp->name, temp->length) == 0) {
+ if (temp->length == otemp->length
+ && bcmp (temp->name, otemp->name, temp->length) == 0) {
error ("duplicate argument name `%.*s' in `#define'",
temp->length, temp->name);
goto nope;
for (p = symname; is_idchar[*p]; p++)
;
sym_length = p - symname;
- if (sym_length == 0)
+ if (sym_length == 0
+ || (sym_length == 1 && *symname == 'L' && (*p == '\'' || *p == '"')))
error ("invalid %s name", usage);
else if (!is_idstart[*symname]
|| (sym_length == 7 && ! bcmp (symname, "defined", 7)))
p++;
SKIP_WHITE_SPACE (p);
}
- if (! is_idstart[*p] || nargs == 0)
+ if (! is_idstart[*p] || nargs == 0
+ || (*p == 'L' && (p[1] == '\'' || p[1] == '"')))
error ("`#' operator is not followed by a macro argument name");
else
stringify = p;
while (p != limit && is_idchar[*p]) p++;
id_len = p - id_beg;
- if (is_idstart[c]) {
+ if (is_idstart[c]
+ && ! (id_len == 1 && c == 'L' && (*p == '\'' || *p == '"'))) {
register struct arglist *arg;
for (arg = arglist; arg != NULL; arg = arg->next) {
}
}
- hash_bucket =
- &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
+ hash_bucket = &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
for (hp = *hash_bucket; hp != NULL; hp = hp->next)
if (hp->length == fname_length &&
bcmp (hp->value.cpval, fname, fname_length) == 0) {
struct directive *keyword;
{
int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+ U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy ((char *) buf, (char *) copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
struct directive *keyword;
{
int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+ U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy ((char *) buf, (char *) copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
- warning ("#warning %s", copy);
+ /* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
+ if -pedantic-errors is given, #warning should cause an error. */
+ pedwarn ("#warning %s", copy);
return 0;
}
if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
error ("`#elif' after `#else'");
fprintf (stderr, " (matches line %d", if_stack->lineno);
- if (if_stack->fname != NULL && ip->fname != NULL &&
- strcmp (if_stack->fname, ip->nominal_fname) != 0)
+ if (if_stack->fname != NULL && ip->fname != NULL
+ && strcmp (if_stack->fname, ip->nominal_fname) != 0)
fprintf (stderr, ", file %s", if_stack->fname);
fprintf (stderr, ")\n");
}
if (pcp_outfile) {
/* Output a precondition for this macro. */
- if (hp &&
- (hp->type == T_CONST
- || (hp->type == T_MACRO && hp->value.defn->predefined)))
+ if (hp
+ && (hp->type == T_CONST
+ || (hp->type == T_MACRO && hp->value.defn->predefined)))
fprintf (pcp_outfile, "#define %s\n", hp->name);
else {
U_CHAR *cp = buf;
}
}
- /* Don't output a line number of 0 if we can help it. */
- if (ip->lineno == 0 && ip->bufp - ip->buf < ip->length
- && *ip->bufp == '\n') {
+ /* Output a positive line number if possible. */
+ while (ip->lineno <= 0 && ip->bufp - ip->buf < ip->length
+ && *ip->bufp == '\n') {
ip->lineno++;
ip->bufp++;
}
VMS file specification. */
static void
-hack_vms_include_specification (fname)
+hack_vms_include_specification (fname, vaxc_include)
char *fname;
+ int vaxc_include;
{
register char *cp, *cp1, *cp2;
int f, check_filename_before_returning;
* Check if we have a vax-c style '#include filename'
* and add the missing .h
*/
- if (!index (cp,'.'))
+ if (vaxc_include && !index (cp,'.'))
strcat (cp, ".h");
cp2 = Local; /* initialize */
\f
#ifdef VMS
-/* These are the read/write replacement routines for
- VAX-11 "C". They make read/write behave enough
- like their UNIX counterparts that CCCP will work */
-
-static int
-read (fd, buf, size)
- int fd;
- char *buf;
- int size;
-{
-#undef read /* Get back the REAL read routine */
- register int i;
- register int total = 0;
-
- /* Read until the buffer is exhausted */
- while (size > 0) {
- /* Limit each read to 32KB */
- i = (size > (32*1024)) ? (32*1024) : size;
- i = read (fd, buf, i);
- if (i <= 0) {
- if (i == 0) return (total);
- return (i);
- }
- /* Account for this read */
- total += i;
- buf += i;
- size -= i;
- }
- return (total);
-}
-
-static int
-write (fd, buf, size)
- int fd;
- char *buf;
- int size;
-{
-#undef write /* Get back the REAL write routine */
- int i;
- int j;
-
- /* Limit individual writes to 32Kb */
- i = size;
- while (i > 0) {
- j = (i > (32*1024)) ? (32*1024) : i;
- if (write (fd, buf, j) < 0) return (-1);
- /* Account for the data written */
- buf += j;
- i -= j;
- }
- return (size);
-}
-
/* The following wrapper functions supply additional arguments to the VMS
I/O routines to optimize performance with file handling. The arguments
are: