⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpplib.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	case '\"':	  goto scan_directive_token;	  break;	case '/':	  nextc = PEEKC();	  if (nextc == '*' || (opts->cplusplus_comments && nextc == '*'))	    goto scan_directive_token;	  break;	case '\f':	case '\v':	  if (CPP_PEDANTIC (pfile))	    cpp_pedwarn (pfile, "%s in preprocessing directive",			 c == '\f' ? "formfeed" : "vertical tab");	  break;	case '\n':	  FORWARD(-1);	  goto end_directive;	scan_directive_token:	  FORWARD(-1);	  cpp_get_token (pfile);	  continue;	}      CPP_PUTC (pfile, c);    } end_directive: ;  CPP_NUL_TERMINATE (pfile);}voidskip_rest_of_line (pfile)     cpp_reader *pfile;{  long old = CPP_WRITTEN (pfile);  copy_rest_of_line (pfile);  CPP_SET_WRITTEN (pfile, old);}/* Handle a possible # directive.   '#' has already been read.  */inthandle_directive (pfile)     cpp_reader *pfile;{ int c;  register struct directive *kt;  int ident_length;  long after_ident;  U_CHAR *ident, *line_end;  long old_written = CPP_WRITTEN (pfile);  cpp_skip_hspace (pfile);  c = PEEKC ();  if (c >= '0' && c <= '9')    {      /* Handle # followed by a line number.  */      if (CPP_PEDANTIC (pfile))	cpp_pedwarn (pfile, "`#' followed by integer");      do_line (pfile, NULL);      goto done_a_directive;    }  /* Now find the directive name. */  CPP_PUTC (pfile, '#');  parse_name (pfile, GETC());  ident = pfile->token_buffer + old_written + 1;  ident_length = CPP_PWRITTEN (pfile) - ident;  if (ident_length == 0 && PEEKC() == '\n')    {      /* A line of just `#' becomes blank.  */      goto done_a_directive;    }#if 0  if (ident_length == 0 || !is_idstart[*ident]) {    U_CHAR *p = ident;    while (is_idchar[*p]) {      if (*p < '0' || *p > '9')	break;      p++;    }    /* Avoid error for `###' and similar cases unless -pedantic.  */    if (p == ident) {      while (*p == '#' || is_hor_space[*p]) p++;      if (*p == '\n') {	if (pedantic && !lang_asm)	  cpp_warning (pfile, "invalid preprocessor directive");	return 0;      }    }    if (!lang_asm)      cpp_error (pfile, "invalid preprocessor directive name");    return 0;  }#endif  /*   * Decode the keyword and call the appropriate expansion   * routine, after moving the input pointer up to the next line.   */  for (kt = directive_table; ; kt++) {    if (kt->length <= 0)      goto not_a_directive;    if (kt->length == ident_length && !strncmp (kt->name, ident, ident_length))       break;  }  if (! kt->command_reads_line)    {      /* Nonzero means do not delete comments within the directive.         #define needs this when -traditional.  */	int comments = CPP_TRADITIONAL (pfile) && kt->traditional_comments; 	int save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;	CPP_OPTIONS (pfile)->put_out_comments = comments;	after_ident = CPP_WRITTEN (pfile);	copy_rest_of_line (pfile);	CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;    }  /* For #pragma and #define, we may want to pass through the directive.     Other directives may create output, but we don't want the directive     itself out, so we pop it now.  For example #include may write a #line     command (see comment in do_include), and conditionals may emit     #failed ... #endfailed stuff.  But note that popping the buffer     means the parameters to kt->func may point after pfile->limit     so these parameters are invalid as soon as something gets appended     to the token_buffer.  */  line_end = CPP_PWRITTEN (pfile);  if (!kt->pass_thru && kt->type != T_DEFINE)    CPP_SET_WRITTEN (pfile, old_written);  (*kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);  if (kt->pass_thru      || (kt->type == T_DEFINE	  && CPP_OPTIONS (pfile)->dump_macros == dump_definitions))    {      /* Just leave the entire #define in the output stack. */    }  else if (kt->type == T_DEFINE	   && CPP_OPTIONS (pfile)->dump_macros == dump_names)    {      U_CHAR *p = pfile->token_buffer + old_written + 7;  /* Skip "#define". */      SKIP_WHITE_SPACE (p);      while (is_idchar[*p]) p++;      pfile->limit = p;      CPP_PUTC (pfile, '\n');    }  else if (kt->type == T_DEFINE)    CPP_SET_WRITTEN (pfile, old_written); done_a_directive:  return 1; not_a_directive:  return 0;}/* Pass a directive through to the output file.   BUF points to the contents of the directive, as a contiguous string.   LIMIT points to the first character past the end of the directive.   KEYWORD is the keyword-table entry for the directive.  */static voidpass_thru_directive (buf, limit, pfile, keyword)     U_CHAR *buf, *limit;     cpp_reader *pfile;     struct directive *keyword;{  register unsigned keyword_length = keyword->length;  CPP_RESERVE (pfile, 1 + keyword_length + (limit - buf));  CPP_PUTC_Q (pfile, '#');  CPP_PUTS_Q (pfile, keyword->name, keyword_length);  if (limit != buf && buf[0] != ' ')    CPP_PUTC_Q (pfile, ' ');  CPP_PUTS_Q (pfile, buf, limit - buf);#if 0  CPP_PUTS_Q (pfile, '\n');  /* Count the line we have just made in the output,     to get in sync properly.  */  pfile->lineno++;#endif}/* The arglist structure is built by do_define to tell   collect_definition where the argument names begin.  That   is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist   would contain pointers to the strings x, y, and z.   Collect_definition would then build a DEFINITION node,   with reflist nodes pointing to the places x, y, and z had   appeared.  So the arglist is just convenience data passed   between these two routines.  It is not kept around after   the current #define has been processed and entered into the   hash table. */struct arglist {  struct arglist *next;  U_CHAR *name;  int length;  int argno;  char rest_args;};/* Read a replacement list for a macro with parameters.   Build the DEFINITION structure.   Reads characters of text starting at BUF until END.   ARGLIST specifies the formal parameters to look for   in the text of the definition; NARGS is the number of args   in that list, or -1 for a macro name that wants no argument list.   MACRONAME is the macro name itself (so we can avoid recursive expansion)   and NAMELEN is its length in characters.      Note that comments, backslash-newlines, and leading white space   have already been deleted from the argument.  */static DEFINITION *collect_expansion (pfile, buf, limit, nargs, arglist)     cpp_reader *pfile;     U_CHAR *buf, *limit;     int nargs;     struct arglist *arglist;{  DEFINITION *defn;  register U_CHAR *p, *lastp, *exp_p;  struct reflist *endpat = NULL;  /* Pointer to first nonspace after last ## seen.  */  U_CHAR *concat = 0;  /* Pointer to first nonspace after last single-# seen.  */  U_CHAR *stringify = 0;  int maxsize;  int expected_delimiter = '\0';  /* Scan thru the replacement list, ignoring comments and quoted     strings, picking up on the macro calls.  It does a linear search     thru the arg list on every potential symbol.  Profiling might say     that something smarter should happen. */  if (limit < buf)    abort ();  /* Find the beginning of the trailing whitespace.  */  p = buf;  while (p < limit && is_space[limit[-1]]) limit--;  /* Allocate space for the text in the macro definition.     Leading and trailing whitespace chars need 2 bytes each.     Each other input char may or may not need 1 byte,     so this is an upper bound.  The extra 5 are for invented     leading and trailing newline-marker and final null.  */  maxsize = (sizeof (DEFINITION)	     + (limit - p) + 5);  /* Occurrences of '@' get doubled, so allocate extra space for them. */  while (p < limit)    if (*p++ == '@')      maxsize++;  defn = (DEFINITION *) xcalloc (1, maxsize);  defn->nargs = nargs;  exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);  lastp = exp_p;  p = buf;  /* Add one initial space escape-marker to prevent accidental     token-pasting (often removed by macroexpand). */  *exp_p++ = '@';  *exp_p++ = ' ';  if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {    cpp_error (pfile, "`##' at start of macro definition");    p += 2;  }  /* Process the main body of the definition.  */  while (p < limit) {    int skipped_arg = 0;    register U_CHAR c = *p++;    *exp_p++ = c;    if (!CPP_TRADITIONAL (pfile)) {      switch (c) {      case '\'':      case '\"':        if (expected_delimiter != '\0') {          if (c == expected_delimiter)            expected_delimiter = '\0';        } else          expected_delimiter = c;	break;      case '\\':	if (p < limit && expected_delimiter) {	  /* In a string, backslash goes through	     and makes next char ordinary.  */	  *exp_p++ = *p++;	}	break;      case '@':	/* An '@' in a string or character constant stands for itself,	   and does not need to be escaped. */	if (!expected_delimiter)	  *exp_p++ = c;	break;      case '#':	/* # is ordinary inside a string.  */	if (expected_delimiter)	  break;	if (p < limit && *p == '#') {	  /* ##: concatenate preceding and following tokens.  */	  /* Take out the first #, discard preceding whitespace.  */	  exp_p--;	  while (exp_p > lastp && is_hor_space[exp_p[-1]])	    --exp_p;	  /* Skip the second #.  */	  p++;	  /* Discard following whitespace.  */	  SKIP_WHITE_SPACE (p);	  concat = p;	  if (p == limit)	    cpp_error (pfile, "`##' at end of macro definition");	} else if (nargs >= 0) {	  /* Single #: stringify following argument ref.	     Don't leave the # in the expansion.  */	  exp_p--;	  SKIP_WHITE_SPACE (p);	  if (p == limit || ! is_idstart[*p])	    cpp_error (pfile,		     "`#' operator is not followed by a macro argument name");	  else	    stringify = p;	}	break;      }    } else {      /* In -traditional mode, recognize arguments inside strings and	 and character constants, and ignore special properties of #.	 Arguments inside strings are considered "stringified", but no	 extra quote marks are supplied.  */      switch (c) {      case '\'':      case '\"':	if (expected_delimiter != '\0') {	  if (c == expected_delimiter)	    expected_delimiter = '\0';	} else	  expected_delimiter = c;	break;      case '\\':	/* Backslash quotes delimiters and itself, but not macro args.  */	if (expected_delimiter != 0 && p < limit	    && (*p == expected_delimiter || *p == '\\')) {	  *exp_p++ = *p++;	  continue;	}	break;      case '/':	if (expected_delimiter != '\0') /* No comments inside strings.  */	  break;	if (*p == '*') {	  /* If we find a comment that wasn't removed by handle_directive,	     this must be -traditional.  So replace the comment with	     nothing at all.  */	  exp_p--;	  p += 1;	  while (p < limit && !(p[-2] == '*' && p[-1] == '/'))	    p++;#if 0	  /* Mark this as a concatenation-point, as if it had been ##.  */	  concat = p;#endif	}	break;      }    }    /* Handle the start of a symbol.  */    if (is_idchar[c] && nargs > 0) {      U_CHAR *id_beg = p - 1;      int id_len;      --exp_p;      while (p != limit && is_idchar[*p]) p++;      id_len = p - id_beg;      if (is_idstart[c]) {	register struct arglist *arg;	for (arg = arglist; arg != NULL; arg = arg->next) {	  struct reflist *tpat;	  if (arg->name[0] == c	      && arg->length == id_len	      && strncmp (arg->name, id_beg, id_len) == 0) {	    if (expected_delimiter && CPP_OPTIONS (pfile)->warn_stringify) {	      if (CPP_TRADITIONAL (pfile)) {		cpp_warning (pfile, "macro argument `%.*s' is stringified.",			     id_len, arg->name);	      } else {		cpp_warning (pfile,		    "macro arg `%.*s' would be stringified with -traditional.",			     id_len, arg->name);	      }	    }	    /* If ANSI, don't actually substitute inside a string.  */	    if (!CPP_TRADITIONAL (pfile) && expected_delimiter)	      break;	    /* make a pat node for this arg and append it to the end of	       the pat list */	    tpat = (struct reflist *) xmalloc (sizeof (struct reflist));	    tpat->next = NULL;	    tpat->raw_before = concat == id_beg;	    tpat->raw_after = 0;	    tpat->rest_args = arg->rest_args;	    tpat->stringify = (CPP_TRADITIONAL (pfile)			       ? expected_delimiter != '\0'			       : stringify == id_beg);	    if (endpat == NULL)	      defn->pattern = tpat;	    else	      endpat->next = tpat;	    endpat = tpat;	    tpat->argno = arg->argno;	    tpat->nchars = exp_p - lastp;	    {	      register U_CHAR *p1 = p;	      SKIP_WHITE_SPACE (p1);	      if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')		tpat->raw_after = 1;	    }	    lastp = exp_p;	/* place to start copying from next time */	    skipped_arg = 1;	    break;	  }	}      }      /* If this was not a macro arg, copy it into the expansion.  */      if (! skipped_arg) {	register U_CHAR *lim1 = p;	p = id_beg;	while (p != lim1)	  *exp_p++ = *p++;	if (stringify == id_beg)	  cpp_error (pfile,		   "`#' operator should be followed by a macro argument name");      }    }  }  if (!CPP_TRADITIONAL (pfile) && expected_delimiter == 0)    {      /* If ANSI, put in a "@ " marker to prevent token pasting.         But not if "inside a string" (which in ANSI mode         happens only for -D option).  */      *exp_p++ = '@';      *exp_p++ = ' ';    }  *exp_p = '\0';  defn->length = exp_p - defn->expansion;  /* Crash now if we overrun the allocated size.  */  if (defn->length + 1 > maxsize)    abort ();#if 0/* This isn't worth the time it takes.  */  /* give back excess storage */  defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);#endif  return defn;}/* * special extension string that can be added to the last macro argument to  * allow it to absorb the "rest" of the arguments when expanded.  Ex: * 		#define wow(a, b...)		process (b, a, b) *		{ wow (1, 2, 3); }	->	{ process (2, 3, 1, 2, 3); } *		{ wow (one, two); }	->	{ process (two, one, two); } * if this "rest_arg" is used with the concat token '##' and if it is not * supplied then the token attached to with ## will not be outputted.  Ex: * 		#define wow (a, b...)		process (b ## , a, ## b) *		{ wow (1, 2); }		->	{ process (2, 1, 2); } *		{ wow (one); }		->	{ process (one); { */static char rest_extension[] = "...";#define REST_EXTENSION_LENGTH	(sizeof (rest_extension) - 1)/* Create a DEFINITION node from a #define directive.  Arguments are    as for do_define. */static MACRODEFcreate_definition (buf, limit, pfile, predefinition)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -