Commit 7f2935c7 by Per Bothner

Initial revision

From-SVN: r9191
parent b310a51d
/* Part of CPP library. (memory allocation - xmalloc etc)
Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
static void
memory_full ()
{
fatal ("Memory exhausted.");
}
char *
xmalloc (size)
unsigned size;
{
register char *ptr = (char *) malloc (size);
if (ptr != 0) return (ptr);
memory_full ();
/*NOTREACHED*/
return 0;
}
char *
xrealloc (old, size)
char *old;
unsigned size;
{
register char *ptr = (char *) realloc (old, size);
if (ptr != 0) return (ptr);
memory_full ();
/*NOTREACHED*/
return 0;
}
char *
xcalloc (number, size)
unsigned number, size;
{
register unsigned total = number * size;
register char *ptr = (char *) malloc (total);
if (ptr != 0) {
if (total > 100)
bzero (ptr, total);
else {
/* It's not too long, so loop, zeroing by longs.
It must be safe because malloc values are always well aligned. */
register long *zp = (long *) ptr;
register long *zl = (long *) (ptr + total - 4);
register int i = total - 4;
while (zp < zl)
*zp++ = 0;
if (i < 0)
i = 0;
while (i < total)
ptr[i++] = 0;
}
return ptr;
}
memory_full ();
/*NOTREACHED*/
return 0;
}
/* Default error handlers for CPP Library.
Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
#include "cpplib.h"
#include <stdio.h>
/* This defines "errno" properly for VMS, and gives us EACCES. */
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#ifndef VMS
#ifndef HAVE_STRERROR
extern int sys_nerr;
#if defined(bsd4_4) || defined(__NetBSD__)
extern const char *const sys_errlist[];
#else
extern char *sys_errlist[];
#endif
#else /* HAVE_STERRROR */
char *strerror ();
#endif
#else /* VMS */
char *strerror (int,...);
#endif
/* Print the file names and line numbers of the #include
commands which led to the current file. */
void
cpp_print_containing_files (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip;
int i;
int first = 1;
/* If stack of files hasn't changed since we last printed
this info, don't repeat it. */
if (pfile->input_stack_listing_current)
return;
ip = cpp_file_buffer (pfile);
/* Give up if we don't find a source file. */
if (ip == NULL)
return;
/* Find the other, outer source files. */
while ((ip = CPP_PREV_BUFFER (ip)), ip != CPP_NULL_BUFFER (pfile))
{
long line, col;
cpp_buf_line_and_col (ip, &line, &col);
if (ip->fname != NULL)
{
if (first)
{
first = 0;
fprintf (stderr, "In file included");
}
else
fprintf (stderr, ",\n ");
}
/* start-sanitize-mpw */
#ifdef MPW
fprintf (stderr, " File \"%s\"; Line %d # ", ip->nominal_fname, line);
#else
/* end-sanitize-mpw */
fprintf (stderr, " from %s:%d", ip->nominal_fname, line);
/* start-sanitize-mpw */
#endif /* MPW */
/* end-sanitize-mpw */
}
if (! first)
fprintf (stderr, ":\n");
/* Record we have printed the status as of this time. */
pfile->input_stack_listing_current = 1;
}
void
cpp_print_file_and_line (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip = cpp_file_buffer (pfile);
if (ip != NULL)
{
long line, col;
cpp_buf_line_and_col (ip, &line, &col);
if (pfile->show_column)
fprintf (stderr, "%s:%d:%d: ", ip->nominal_fname, line, col);
else
fprintf (stderr, "%s:%d: ", ip->nominal_fname, line);
}
}
void
cpp_error (pfile, msg, arg1, arg2, arg3)
cpp_reader *pfile;
char *msg;
char *arg1, *arg2, *arg3;
{
cpp_print_containing_files (pfile);
cpp_print_file_and_line (pfile);
fprintf (stderr, msg, arg1, arg2, arg3);
fprintf (stderr, "\n");
pfile->errors++;
}
/* Print error message but don't count it. */
void
cpp_warning (pfile, msg, arg1, arg2, arg3)
cpp_reader *pfile;
char *msg;
char *arg1, *arg2, *arg3;
{
if (CPP_OPTIONS (pfile)->inhibit_warnings)
return;
if (CPP_OPTIONS (pfile)->warnings_are_errors)
pfile->errors++;
cpp_print_containing_files (pfile);
cpp_print_file_and_line (pfile);
fprintf (stderr, "warning: ");
fprintf (stderr, msg, arg1, arg2, arg3);
fprintf (stderr, "\n");
}
void
cpp_error_with_line (pfile, line, msg, arg1, arg2, arg3)
cpp_reader *pfile;
int line;
char *msg;
char *arg1, *arg2, *arg3;
{
int i;
cpp_buffer *ip = cpp_file_buffer (pfile);
cpp_print_containing_files (pfile);
if (ip != NULL)
fprintf (stderr, "%s:%d: ", ip->nominal_fname, line);
fprintf (stderr, msg, arg1, arg2, arg3);
fprintf (stderr, "\n");
pfile->errors++;
}
void
cpp_warning_with_line (pfile, line, msg, arg1, arg2, arg3)
cpp_reader *pfile;
int line;
char *msg;
char *arg1, *arg2, *arg3;
{
int i;
cpp_buffer *ip;
if (CPP_OPTIONS (pfile)->inhibit_warnings)
return;
if (CPP_OPTIONS (pfile)->warnings_are_errors)
pfile->errors++;
cpp_print_containing_files (pfile);
ip = cpp_file_buffer (pfile);
if (ip != NULL)
fprintf (stderr, "%s:%d: ", ip->nominal_fname, line);
fprintf (stderr, "warning: ");
fprintf (stderr, msg, arg1, arg2, arg3);
fprintf (stderr, "\n");
}
/* Print an error message and maybe count it. */
void
cpp_pedwarn (pfile, msg, arg1, arg2, arg3)
cpp_reader *pfile;
char *msg;
char *arg1, *arg2, *arg3;
{
if (CPP_OPTIONS (pfile)->pedantic_errors)
cpp_error (pfile, msg, arg1, arg2, arg3);
else
cpp_warning (pfile, msg, arg1, arg2, arg3);
}
void
cpp_pedwarn_with_line (pfile, line, msg, arg1, arg2, arg3)
cpp_reader *pfile;
int line;
char *msg;
char *arg1, *arg2, *arg3;
{
if (CPP_OPTIONS (pfile)->pedantic_errors)
cpp_error_with_line (pfile, line, msg, arg1, arg2, arg3);
else
cpp_warning_with_line (pfile, line, msg, arg1, arg2, arg3);
}
/* Report a warning (or an error if pedantic_errors)
giving specified file name and line number, not current. */
void
cpp_pedwarn_with_file_and_line (pfile, file, line, msg, arg1, arg2, arg3)
cpp_reader *pfile;
char *file;
int line;
char *msg;
char *arg1, *arg2, *arg3;
{
if (!CPP_OPTIONS (pfile)->pedantic_errors
&& CPP_OPTIONS (pfile)->inhibit_warnings)
return;
if (file != NULL)
fprintf (stderr, "%s:%d: ", file, line);
if (CPP_OPTIONS (pfile)->pedantic_errors)
pfile->errors++;
else
fprintf (stderr, "warning: ");
fprintf (stderr, msg, arg1, arg2, arg3);
fprintf (stderr, "\n");
}
void
fatal (str, arg)
char *str, *arg;
{
fprintf (stderr, "%s: ", progname);
fprintf (stderr, str, arg);
fprintf (stderr, "\n");
exit (FAILURE_EXIT_CODE);
}
/*
* my_strerror - return the descriptive text associated with an `errno' code.
*/
char *
my_strerror (errnum)
int errnum;
{
char *result;
#ifndef VMS
#ifndef HAVE_STRERROR
result = (char *) ((errnum < sys_nerr) ? sys_errlist[errnum] : 0);
#else
result = strerror (errnum);
#endif
#else /* VMS */
/* VAXCRTL's strerror() takes an optional second argument, which only
matters when the first argument is EVMSERR. However, it's simplest
just to pass it unconditionally. `vaxc$errno' is declared in
<errno.h>, and maintained by the library in parallel with `errno'.
We assume that caller's `errnum' either matches the last setting of
`errno' by the library or else does not have the value `EVMSERR'. */
result = strerror (errnum, vaxc$errno);
#endif
if (!result)
result = "undocumented I/O error";
return result;
}
/* Error including a message from `errno'. */
void
cpp_error_from_errno (pfile, name)
cpp_reader *pfile;
char *name;
{
int i;
cpp_buffer *ip = cpp_file_buffer (pfile);
cpp_print_containing_files (pfile);
if (ip != NULL)
fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
pfile->errors++;
}
void
cpp_perror_with_name (pfile, name)
cpp_reader *pfile;
char *name;
{
fprintf (stderr, "%s: ", progname);
fprintf (stderr, "%s: %s\n", name, my_strerror (errno));
pfile->errors++;
}
void
cpp_pfatal_with_name (pfile, name)
cpp_reader *pfile;
char *name;
{
cpp_perror_with_name (pfile, name);
#ifdef VMS
exit (vaxc$errno);
#else
exit (FAILURE_EXIT_CODE);
#endif
}
This diff is collapsed. Click to expand it.
/* Part of CPP library. (Macro hash table support.)
Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
#include "cpplib.h"
#include "cpphash.h"
/* Define a generic NULL if one hasn't already been defined. */
#ifndef NULL
#define NULL 0
#endif
/*
* return hash function on name. must be compatible with the one
* computed a step at a time, elsewhere
*/
int
hashf (name, len, hashsize)
register const U_CHAR *name;
register int len;
int hashsize;
{
register int r = 0;
while (len--)
r = HASHSTEP (r, *name++);
return MAKE_POS (r) % hashsize;
}
/*
* find the most recent hash node for name name (ending with first
* non-identifier char) installed by install
*
* If LEN is >= 0, it is the length of the name.
* Otherwise, compute the length by scanning the entire name.
*
* If HASH is >= 0, it is the precomputed hash code.
* Otherwise, compute the hash code.
*/
HASHNODE *
cpp_lookup (pfile, name, len, hash)
struct parse_file *pfile;
const U_CHAR *name;
int len;
int hash;
{
register const U_CHAR *bp;
register HASHNODE *bucket;
if (len < 0)
{
for (bp = name; is_idchar[*bp]; bp++) ;
len = bp - name;
}
if (hash < 0)
hash = hashf (name, len, HASHSIZE);
bucket = hashtab[hash];
while (bucket) {
if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
return bucket;
bucket = bucket->next;
}
return (HASHNODE*) 0;
}
/*
* Delete a hash node. Some weirdness to free junk from macros.
* More such weirdness will have to be added if you define more hash
* types that need it.
*/
/* Note that the DEFINITION of a macro is removed from the hash table
but its storage is not freed. This would be a storage leak
except that it is not reasonable to keep undefining and redefining
large numbers of macros many times.
In any case, this is necessary, because a macro can be #undef'd
in the middle of reading the arguments to a call to it.
If #undef freed the DEFINITION, that would crash. */
void
delete_macro (hp)
HASHNODE *hp;
{
if (hp->prev != NULL)
hp->prev->next = hp->next;
if (hp->next != NULL)
hp->next->prev = hp->prev;
/* make sure that the bucket chain header that
the deleted guy was on points to the right thing afterwards. */
if (hp == *hp->bucket_hdr)
*hp->bucket_hdr = hp->next;
#if 0
if (hp->type == T_MACRO) {
DEFINITION *d = hp->value.defn;
struct reflist *ap, *nextap;
for (ap = d->pattern; ap != NULL; ap = nextap) {
nextap = ap->next;
free (ap);
}
free (d);
}
#endif
free (hp);
}
/*
* install a name in the main hash table, even if it is already there.
* name stops with first non alphanumeric, except leading '#'.
* caller must check against redefinition if that is desired.
* delete_macro () removes things installed by install () in fifo order.
* this is important because of the `defined' special symbol used
* in #if, and also if pushdef/popdef directives are ever implemented.
*
* If LEN is >= 0, it is the length of the name.
* Otherwise, compute the length by scanning the entire name.
*
* If HASH is >= 0, it is the precomputed hash code.
* Otherwise, compute the hash code.
*/
HASHNODE *
install (name, len, type, ivalue, value, hash)
U_CHAR *name;
int len;
enum node_type type;
int ivalue;
char *value;
int hash;
{
register HASHNODE *hp;
register int i, bucket;
register U_CHAR *p, *q;
if (len < 0) {
p = name;
while (is_idchar[*p])
p++;
len = p - name;
}
if (hash < 0)
hash = hashf (name, len, HASHSIZE);
i = sizeof (HASHNODE) + len + 1;
hp = (HASHNODE *) xmalloc (i);
bucket = hash;
hp->bucket_hdr = &hashtab[bucket];
hp->next = hashtab[bucket];
hashtab[bucket] = hp;
hp->prev = NULL;
if (hp->next != NULL)
hp->next->prev = hp;
hp->type = type;
hp->length = len;
if (hp->type == T_CONST)
hp->value.ival = ivalue;
else
hp->value.cpval = value;
hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
p = hp->name;
q = name;
for (i = 0; i < len; i++)
*p++ = *q++;
hp->name[len] = 0;
return hp;
}
enum node_type;
/* different kinds of things that can appear in the value field
of a hash node. Actually, this may be useless now. */
union hashval {
int ival;
char *cpval;
DEFINITION *defn;
#if 0
KEYDEF *keydef;
#endif
};
struct hashnode {
struct hashnode *next; /* double links for easy deletion */
struct hashnode *prev;
struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash
chain is kept, in case the node is the head
of the chain and gets deleted. */
enum node_type type; /* type of special token */
int length; /* length of token, for quick comparison */
U_CHAR *name; /* the actual name */
union hashval value; /* pointer to expansion, or whatever */
};
typedef struct hashnode HASHNODE;
/* Some definitions for the hash table. The hash function MUST be
computed as shown in hashf () below. That is because the rescan
loop computes the hash value `on the fly' for most tokens,
in order to avoid the overhead of a lot of procedure calls to
the hashf () function. Hashf () only exists for the sake of
politeness, for use when speed isn't so important. */
#define HASHSIZE 1403
static HASHNODE *hashtab[HASHSIZE];
#define HASHSTEP(old, c) ((old << 2) + c)
#define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
extern HASHNODE* install PARAMS ((U_CHAR*,int,enum node_type, int,char*,int));
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed. Click to expand it.
/* CPP main program, using CPP Library.
Copyright (C) 1995 Free Software Foundation, Inc.
Written by Per Bothner, 1994-95.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
#include "cpplib.h"
#include <stdio.h>
extern char *getenv ();
cpp_reader parse_in;
cpp_options options;
/* More 'friendly' abort that prints the line and file.
config.h can #define abort fancy_abort if you like that sort of thing. */
void
fancy_abort ()
{
fatal ("Internal gcc abort.");
}
int
main (argc, argv)
int argc;
char **argv;
{
char *p;
int i;
int argi = 1; /* Next argument to handle. */
struct cpp_options *opts = &options;
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && p[-1] != '/') --p;
progname = p;
init_parse_file (&parse_in);
parse_in.data = opts;
init_parse_options (opts);
argi += cpp_handle_options (&parse_in, argc - argi , argv + argi);
if (argi < argc)
fatal ("Invalid option `%s'", argv[argi]);
parse_in.show_column = 1;
i = push_parse_file (&parse_in, opts->in_fname);
if (i != SUCCESS_EXIT_CODE)
return i;
/* Now that we know the input file is valid, open the output. */
if (!opts->out_fname || !strcmp (opts->out_fname, ""))
opts->out_fname = "stdout";
else if (! freopen (opts->out_fname, "w", stdout))
cpp_pfatal_with_name (&parse_in, opts->out_fname);
for (;;)
{
#if 0
int ch = PARSE_GETC (&parse_in);
if (ch < 0)
break;
if (! opts->no_output)
putchar (ch);
#else
enum cpp_token kind;
if (! opts->no_output)
{
fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (&parse_in), stdout);
}
parse_in.limit = parse_in.token_buffer;
kind = cpp_get_token (&parse_in);
if (kind == CPP_EOF)
break;
#endif
}
cpp_finish (&parse_in);
if (parse_in.errors)
exit (FAILURE_EXIT_CODE);
exit (SUCCESS_EXIT_CODE);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment