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

📄 cpplib.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
     U_CHAR *buf, *limit;     cpp_reader *pfile;     int predefinition;{  U_CHAR *bp;			/* temp ptr into input buffer */  U_CHAR *symname;		/* remember where symbol name starts */  int sym_length;		/* and how long it is */  int rest_args = 0;  long line, col;  char *file = CPP_BUFFER (pfile) ? CPP_BUFFER (pfile)->nominal_fname : "";  DEFINITION *defn;  int arglengths = 0;		/* Accumulate lengths of arg names				   plus number of args.  */  MACRODEF mdef;  cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);  bp = buf;  while (is_hor_space[*bp])    bp++;  symname = bp;			/* remember where it starts */  sym_length = check_macro_name (pfile, bp, "macro");  bp += sym_length;  /* Lossage will occur if identifiers or control keywords are broken     across lines using backslash.  This is not the right place to take     care of that. */  if (*bp == '(') {    struct arglist *arg_ptrs = NULL;    int argno = 0;    bp++;			/* skip '(' */    SKIP_WHITE_SPACE (bp);    /* Loop over macro argument names.  */    while (*bp != ')') {      struct arglist *temp;      temp = (struct arglist *) alloca (sizeof (struct arglist));      temp->name = bp;      temp->next = arg_ptrs;      temp->argno = argno++;      temp->rest_args = 0;      arg_ptrs = temp;      if (rest_args)	cpp_pedwarn (pfile, "another parameter follows `%s'", rest_extension);      if (!is_idstart[*bp])	cpp_pedwarn (pfile, "invalid character in macro parameter name");            /* Find the end of the arg name.  */      while (is_idchar[*bp]) {	bp++;	/* do we have a "special" rest-args extension here? */	if (limit - bp > REST_EXTENSION_LENGTH &&	    strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {	  rest_args = 1;	  temp->rest_args = 1;	  break;	}      }      temp->length = bp - temp->name;      if (rest_args == 1)	bp += REST_EXTENSION_LENGTH;      arglengths += temp->length + 2;      SKIP_WHITE_SPACE (bp);      if (temp->length == 0 || (*bp != ',' && *bp != ')')) {	cpp_error (pfile, "badly punctuated parameter list in `#define'");	goto nope;      }      if (*bp == ',') {	bp++;	SKIP_WHITE_SPACE (bp);      }      if (bp >= limit) {	cpp_error (pfile, "unterminated parameter list in `#define'");	goto nope;      }      {	struct arglist *otemp;	for (otemp = temp->next; otemp != NULL; otemp = otemp->next)	  if (temp->length == otemp->length &&	    strncmp (temp->name, otemp->name, temp->length) == 0) {	      U_CHAR *name;	      name = (U_CHAR *) alloca (temp->length + 1);	      (void) strncpy (name, temp->name, temp->length);	      name[temp->length] = '\0';	      cpp_error (pfile,			 "duplicate argument name `%s' in `#define'", name);	      goto nope;	  }      }    }    ++bp;			/* skip paren */    SKIP_WHITE_SPACE (bp);    /* now everything from bp before limit is the definition. */    defn = collect_expansion (pfile, bp, limit, argno, arg_ptrs);    defn->rest_args = rest_args;    /* Now set defn->args.argnames to the result of concatenating       the argument names in reverse order       with comma-space between them.  */    defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);    {      struct arglist *temp;      int i = 0;      for (temp = arg_ptrs; temp; temp = temp->next) {	bcopy (temp->name, &defn->args.argnames[i], temp->length);	i += temp->length;	if (temp->next != 0) {	  defn->args.argnames[i++] = ',';	  defn->args.argnames[i++] = ' ';	}      }      defn->args.argnames[i] = 0;    }  } else {    /* Simple expansion or empty definition.  */    if (bp < limit)      {	if (is_hor_space[*bp]) {	  bp++;	  SKIP_WHITE_SPACE (bp);	} else {	  switch (*bp) {	    case '!':  case '"':  case '#':  case '%':  case '&':  case '\'':	    case ')':  case '*':  case '+':  case ',':  case '-':  case '.':	    case '/':  case ':':  case ';':  case '<':  case '=':  case '>':	    case '?':  case '[':  case '\\': case ']':  case '^':  case '{':	    case '|':  case '}':  case '~':	      cpp_warning (pfile, "missing white space after `#define %.*s'",			   sym_length, symname);	      break;	    default:	      cpp_pedwarn (pfile, "missing white space after `#define %.*s'",			   sym_length, symname);	      break;	  }	}      }    /* now everything from bp before limit is the definition. */    defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);    defn->args.argnames = (U_CHAR *) "";  }  defn->line = line;  defn->file = file;  /* OP is null if this is a predefinition */  defn->predefined = predefinition;  mdef.defn = defn;  mdef.symnam = symname;  mdef.symlen = sym_length;  return mdef; nope:  mdef.defn = 0;  return mdef;}/* Check a purported macro name SYMNAME, and yield its length.   USAGE is the kind of name this is intended for.  */static intcheck_macro_name (pfile, symname, usage)     cpp_reader *pfile;     U_CHAR *symname;     char *usage;{  U_CHAR *p;  int sym_length;  for (p = symname; is_idchar[*p]; p++)    ;  sym_length = p - symname;  if (sym_length == 0)    cpp_error (pfile, "invalid %s name", usage);  else if (!is_idstart[*symname]) {    U_CHAR *msg;			/* what pain... */    msg = (U_CHAR *) alloca (sym_length + 1);    bcopy (symname, msg, sym_length);    msg[sym_length] = 0;    cpp_error (pfile, "invalid %s name `%s'", usage, msg);  } else {    if (! strncmp (symname, "defined", 7) && sym_length == 7)      cpp_error (pfile, "invalid %s name `defined'", usage);  }  return sym_length;}/* * return zero if two DEFINITIONs are isomorphic */static intcompare_defs (d1, d2)     DEFINITION *d1, *d2;{  register struct reflist *a1, *a2;  register U_CHAR *p1 = d1->expansion;  register U_CHAR *p2 = d2->expansion;  int first = 1;  if (d1->nargs != d2->nargs)    return 1;  if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))    return 1;  for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;       a1 = a1->next, a2 = a2->next) {    if (!((a1->nchars == a2->nchars && ! strncmp (p1, p2, a1->nchars))	  || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))	|| a1->argno != a2->argno	|| a1->stringify != a2->stringify	|| a1->raw_before != a2->raw_before	|| a1->raw_after != a2->raw_after)      return 1;    first = 0;    p1 += a1->nchars;    p2 += a2->nchars;  }  if (a1 != a2)    return 1;  if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),		     p2, d2->length - (p2 - d2->expansion), 1))    return 1;  return 0;}/* Return 1 if two parts of two macro definitions are effectively different.   One of the parts starts at BEG1 and has LEN1 chars;   the other has LEN2 chars at BEG2.   Any sequence of whitespace matches any other sequence of whitespace.   FIRST means these parts are the first of a macro definition;    so ignore leading whitespace entirely.   LAST means these parts are the last of a macro definition;    so ignore trailing whitespace entirely.  */static intcomp_def_part (first, beg1, len1, beg2, len2, last)     int first;     U_CHAR *beg1, *beg2;     int len1, len2;     int last;{  register U_CHAR *end1 = beg1 + len1;  register U_CHAR *end2 = beg2 + len2;  if (first) {    while (beg1 != end1 && is_space[*beg1]) beg1++;    while (beg2 != end2 && is_space[*beg2]) beg2++;  }  if (last) {    while (beg1 != end1 && is_space[end1[-1]]) end1--;    while (beg2 != end2 && is_space[end2[-1]]) end2--;  }  while (beg1 != end1 && beg2 != end2) {    if (is_space[*beg1] && is_space[*beg2]) {      while (beg1 != end1 && is_space[*beg1]) beg1++;      while (beg2 != end2 && is_space[*beg2]) beg2++;    } else if (*beg1 == *beg2) {      beg1++; beg2++;    } else break;  }  return (beg1 != end1) || (beg2 != end2);}/* Process a #define command.BUF points to the contents of the #define command, as a contiguous string.LIMIT points to the first character past the end of the definition.KEYWORD is the keyword-table entry for #define,or NULL for a "predefined" macro.  */static intdo_define (pfile, keyword, buf, limit)     cpp_reader *pfile;     struct directive *keyword;     U_CHAR *buf, *limit;{  int hashcode;  MACRODEF mdef;  HASHNODE *hp;#if 0  /* If this is a precompiler run (with -pcp) pass thru #define commands.  */  if (pcp_outfile && keyword)    pass_thru_directive (buf, limit, pfile, keyword);#endif  mdef = create_definition (buf, limit, pfile, keyword == NULL);  if (mdef.defn == 0)    goto nope;  hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE);  if ((hp = cpp_lookup (pfile, mdef.symnam, mdef.symlen, hashcode)) != NULL)    {      int ok = 0;      /* Redefining a precompiled key is ok.  */      if (hp->type == T_PCSTRING)	ok = 1;      /* Redefining a macro is ok if the definitions are the same.  */      else if (hp->type == T_MACRO)	ok = ! compare_defs (mdef.defn, hp->value.defn);      /* Redefining a constant is ok with -D.  */      else if (hp->type == T_CONST)        ok = ! CPP_OPTIONS (pfile)->done_initializing;      /* Print the warning if it's not ok.  */      if (!ok)	{	  U_CHAR *msg;		/* what pain... */	  /* If we are passing through #define and #undef directives, do	     that for this re-definition now.  */	  if (CPP_OPTIONS (pfile)->debug_output && keyword)	    pass_thru_directive (buf, limit, pfile, keyword);	  msg = (U_CHAR *) alloca (mdef.symlen + 22);	  *msg = '`';	  bcopy (mdef.symnam, msg + 1, mdef.symlen);	  strcpy ((char *) (msg + mdef.symlen + 1), "' redefined");	  cpp_pedwarn (pfile, msg);	  if (hp->type == T_MACRO)	    cpp_pedwarn_with_file_and_line (pfile, hp->value.defn->file, hp->value.defn->line,				      "this is the location of the previous definition");	}      /* Replace the old definition.  */      hp->type = T_MACRO;      hp->value.defn = mdef.defn;    }  else    {      /* If we are passing through #define and #undef directives, do	 that for this new definition now.  */      if (CPP_OPTIONS (pfile)->debug_output && keyword)	pass_thru_directive (buf, limit, pfile, keyword);      install (mdef.symnam, mdef.symlen, T_MACRO, 0,	       (char *) mdef.defn, hashcode);    }  return 0;nope:  return 1;}/* This structure represents one parsed argument in a macro call.   `raw' points to the argument text as written (`raw_length' is its length).   `expanded' points to the argument's macro-expansion   (its length is `expand_length').   `stringified_length' is the length the argument would have   if stringified.   `use_count' is the number of times this macro arg is substituted   into the macro.  If the actual use count exceeds 10,    the value stored is 10. *//* raw and expanded are relative to ARG_BASE */#define ARG_BASE ((pfile)->token_buffer)struct argdata {  /* Strings relative to pfile->token_buffer */  long raw, expanded, stringified;  int raw_length, expand_length;  int stringified_length;  char newlines;  char use_count;};cpp_buffer*cpp_push_buffer (pfile, buffer, length)     cpp_reader *pfile;     U_CHAR *buffer;     long length;{#ifdef STATIC_BUFFERS  register cpp_buffer *buf = CPP_BUFFER (pfile);  if (buf == pfile->buffer_stack)    fatal ("%s: macro or `#include' recursion too deep", buf->fname);  buf--;  bzero ((char *) buf, sizeof (cpp_buffer));  CPP_BUFFER (pfile) = buf;#else  register cpp_buffer *buf = (cpp_buffer*) xmalloc (sizeof(cpp_buffer));  bzero ((char *) buf, sizeof (cpp_buffer));  CPP_PREV_BUFFER (buf) = CPP_BUFFER (pfile);  CPP_BUFFER (pfile) = buf;#endif  buf->if_stack = pfile->if_stack;  buf->cleanup = null_cleanup;  buf->underflow = null_underflow;  buf->buf = buf->cur = buffer;  buf->alimit = buf->rlimit = buffer + length;    return buf;}cpp_buffer*cpp_pop_buffer (pfile)     cpp_reader *pfile;{  cpp_buffer *buf = CPP_BUFFER (pfile);#ifdef STATIC_BUFFERS  (*buf->cleanup) (buf, pfile);  return ++CPP_BUFFER (pfile);#else  cpp_buffer *next_buf = CPP_PREV_BUFFER (buf);  (*buf->cleanup) (buf, pfile);  CPP_BUFFER (pfile) = next_buf;  free (buf);  return next_buf;#endif}/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer.   Pop the buffer when done. */voidcpp_scan_buffer (pfile)     cpp_reader *pfile;{  cpp_buffer *buffer = CPP_BUFFER (pfile);  for (;;)    {      enum cpp_token token = cpp_get_token (pfile);      if (token == CPP_EOF) /* Should not happen ... */	break;      if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)	{	  cpp_pop_buffer (pfile);	  break;	}    }}/* * Rescan a string (which may have escape marks) into pfile's buffer. * Place the result in pfile->token_buffer. * * The input is copied before it is scanned, so it is safe to pass * it something from the token_buffer that will get overwritten * (because it follows CPP_WRITTEN).  This is used by do_include. */static voidcpp_expand_to_buffer (pfile, buf, length)     cpp_reader *pfile;     U_CHAR *buf;     int length;{  register cpp_buffer *ip;  cpp_buffer obuf;  U_CHAR *limit = buf + length;  U_CHAR *buf1;#if 0  int odepth = indepth;#endif  if (length < 0)    abort ();  /* Set up the input on the input stack.  */  buf1 = (U_CHAR *) alloca (length + 1);  {    register U_CHAR *p1 = buf;    register U_CHAR *p2 = buf1;    while (p1 != limit)      *p2++ = *p1++;  }  buf1[length] = 0;  ip = cpp_push_buffer (pfile, buf1, length);  ip->has_escapes = 1;#if 0  ip->lineno = obuf.lineno = 1;#endif  /* Scan the input, create the output.  */  cpp_scan_buffer (pfile);#if 0  if (indepth != odepth)    abort ();#endif  CPP_NUL_TERMINATE (pfile);}static voidadjust_position (buf, limit, linep, colp)     U_CHAR *buf;     U_CHAR *limit;

⌨️ 快捷键说明

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