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

📄 cccp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
IF_STACK_FRAME *if_stack = NULL;/* * handle #if command by *   1) inserting special `defined' keyword into the hash table *	that gets turned into 0 or 1 by expand_special_symbol (thus, *	if the luser has a symbol called `defined' already, it won't *      work inside the #if command) *   2) rescan the input into a temporary output buffer *   3) pass the output buffer to the yacc parser and collect a value *   4) clean up the mess left from steps 1 and 2. *   5) call conditional_skip to skip til the next #endif (etc.), *      or not, depending on the value from step 3. */do_if (buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  int value;  FILE_BUF *ip = &instack[indepth - 1];  value = eval_if_expression (buf, limit - buf);  conditional_skip (ip, value == 0, T_IF);}/* * handle a #elif directive by not changing  if_stack  either. * see the comment above do_else. */do_elif (buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  int value;  FILE_BUF *ip = &instack[indepth - 1];  if (if_stack == NULL)    error ("if-less #elif");  else {    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->fname) != 0)	fprintf (stderr, ", file %s", if_stack->fname);      fprintf(stderr, ")\n");    }    if_stack->type = T_ELIF;  }    value = eval_if_expression (buf, limit - buf);  conditional_skip (ip, value == 0, T_ELIF);}/* * evaluate a #if expression in BUF, of length LENGTH, * making careful arrangements to handle `defined' and * prepare for calling the yacc parser. */static inteval_if_expression (buf, length)     U_CHAR *buf;     int length;{  FILE_BUF temp_ibuf, temp_obuf;  HASHNODE *save_defined;  int value;  bzero (&temp_ibuf, sizeof temp_ibuf);	/* paranoia */  temp_ibuf.length = length;  temp_ibuf.buf = temp_ibuf.bufp = buf;  temp_obuf.length = length;  temp_obuf.bufp = temp_obuf.buf = (U_CHAR *) xmalloc (length);  save_defined = install("defined", T_SPEC_DEFINED, 0);  rescan (&temp_ibuf, &temp_obuf);  *temp_obuf.bufp = '\0';  value = parse_c_expression(temp_obuf.buf);  delete (save_defined);	/* clean up special symbol */  free (temp_obuf.buf);    return value;}/* * routine to handle ifdef/ifndef.  Try to look up the symbol, * then do or don't skip to the #endif/#else/#elif depending * on what directive is actually being processed. */do_xifdef (buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  HASHNODE *lookup();  int skip;  FILE_BUF *ip = &instack[indepth - 1];  SKIP_WHITE_SPACE (buf);  skip = (lookup(buf) == NULL) ^ (keyword->type == T_IFNDEF);  conditional_skip (ip, skip, T_IF);}/* * push TYPE on stack; then, if SKIP is nonzero, skip ahead. */staticconditional_skip (ip, skip, type)     FILE_BUF *ip;     int skip, type;{  IF_STACK_FRAME *temp;  temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));  temp->fname = ip->fname;  temp->lineno = ip->lineno;  temp->next = if_stack;  if_stack = temp;  if_stack->type = type;    if (skip != 0) {    skip_if_group(ip);    return;  } else {    ++if_stack->if_succeeded;    output_line_command(ip, &outbuf);	/* JF */  }}/* * skip to #endif, #else, or #elif.  adjust line numbers, etc. * leaves input ptr at the sharp sign found. */staticskip_if_group(ip)     FILE_BUF *ip;{  register U_CHAR *bp = ip->bufp, *cp;  register U_CHAR *endb = ip->buf + ip->length;  struct keyword_table *kt;  U_CHAR *save_sharp, *skip_to_end_of_comment (), *skip_quoted_string ();  IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */  while (bp <= endb) {    switch (*bp++) {    case '/':			/* possible comment */      if (*bp == '*') {	ip->bufp = ++bp;	bp = skip_to_end_of_comment (ip, &ip->lineno);      }      break;    case '\"':    case '\'':      ip->bufp = bp - 1;      bp = skip_quoted_string (ip, NULL);	/* JF was (ip) */      break;    case '\n':      ++ip->lineno;      break;    case '#':      /* # keyword: the # must be first nonblank char on the line */      for (cp = bp - 1; cp >= ip->buf; cp--)	if (*cp == '\n')	  break;      cp++;			/* skip nl or move back into buffer */      SKIP_WHITE_SPACE (cp);      if (cp != bp - 1)	/* ????? */	break;      save_sharp = cp;		/* point at '#' */      SKIP_WHITE_SPACE (bp);      for (kt = keyword_table; kt->length >= 0; kt++) {	IF_STACK_FRAME *temp;	if (strncmp(bp, kt->name, kt->length) == 0	    && !is_idchar[bp[kt->length]]) {	  switch (kt->type) {	  case T_IF:	  case T_IFDEF:	  case T_IFNDEF:	    temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));	    temp->next = if_stack;	    if_stack = temp;	    temp->lineno = ip->lineno;	    temp->fname = ip->fname;	    temp->type = kt->type;	    break;	  case T_ELSE:	  case T_ELIF:	  case T_ENDIF:	    ip->bufp = save_sharp;	    if (if_stack == NULL) {	      U_CHAR msg[50];	      sprintf (msg, "if-less #%s", kt->name);	      error (msg);	      break;	    }	    else if (if_stack == save_if_stack)	      return;		/* found what we came for */	    if (kt->type != T_ENDIF) {	      if (if_stack->type == T_ELSE)		error ("#else or #elif after #else");	      if_stack->type = kt->type;	      break;	    }	    temp = if_stack;	    if_stack = if_stack->next;	    free (temp);	    break;	  }	}      }    }  }  ip->bufp = bp;  ip->lineno = instack->lineno; /* bufp won't be right, though */  error ("unterminated #if/#ifdef/#ifndef conditional");  /* after this returns, the main loop will exit because ip->bufp     now points to the end of the buffer.  I am not sure whether     this is dirty or not. */  return;}/* * handle a #else directive.  Do this by just continuing processing * without changing  if_stack ;  this is so that the error message * for missing #endif's etc. will point to the original #if.  It * is possible that something different would be better. */ do_else(buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  register U_CHAR *bp;  FILE_BUF *ip = &instack[indepth - 1];  if (if_stack == NULL) {    error ("if-less #else");    return;  } else {    if (if_stack->type != T_IF && if_stack->type != T_ELIF) {      error ("#else after #else");      fprintf (stderr, " (matches line %d", if_stack->lineno);      if (strcmp(if_stack->fname, ip->fname) != 0)	fprintf (stderr, ", file %s", if_stack->fname);      fprintf(stderr, ")\n");    }    if_stack->type = T_ELSE;  }  if (if_stack->if_succeeded)    skip_if_group (ip);  else {    ++if_stack->if_succeeded;	/* continue processing input */    output_line_command(ip, op);	/* JF try to keep line #s right? */  }}/* * unstack after #endif command */do_endif(buf, limit, op, keyword)     U_CHAR *buf, *limit;     FILE_BUF *op;     struct keyword_table *keyword;{  register U_CHAR *bp;  if (if_stack == NULL)    error ("if-less #endif");  else {    IF_STACK_FRAME *temp = if_stack;    if_stack = if_stack->next;    free (temp);    /* JF try to keep line #s right? */    output_line_command (&instack[indepth - 1], op);  }}/* * Skip a comment, assuming the input ptr immediately follows the * initial slash-star.  Bump line counter as necessary. * (The canonical line counter is &ip->lineno). * Don't use this routine (or the next one) if bumping the line * counter is not sufficient to deal with newlines in the string. */U_CHAR *skip_to_end_of_comment (ip, line_counter)     register FILE_BUF *ip;     int *line_counter;		/* place to remember newlines, or NULL */{  register U_CHAR *limit = ip->buf + ip->length;  register U_CHAR *bp = ip->bufp;  FILE_BUF *op = &outbuf;	/* JF */	/* JF this line_counter stuff is a crock to make sure the	   comment is only put out once, no matter how many times	   the comment is skipped.  It almost works */  if (put_out_comments && !line_counter) {    *op->bufp++ = '/';    *op->bufp++ = '*';  }  while (bp < limit) {    if (put_out_comments && !line_counter)      *op->bufp++ = *bp;    switch (*bp++) {    case '\n':      if (line_counter != NULL)	++*line_counter;      break;    case '*':      if (*bp == '/') {        if (put_out_comments && !line_counter)	  *op->bufp++ = '/';	ip->bufp = ++bp;	return bp;      }      break;    }  }  ip->bufp = bp;  return bp;}/* * skip over a quoted string.  Unlike skip_to_end_of_comment, this * wants ip->bufp at the beginning quote, not after it.  this is so we * can tell what kind of quote to match.  return if unescaped eol is * encountered --- it is probably some sort of error in the input. */U_CHAR *skip_quoted_string (ip, count_newlines)     register FILE_BUF *ip;     int count_newlines;{  register U_CHAR *limit = ip->buf + ip->length;  register U_CHAR *bp = ip->bufp;  register U_CHAR c, match;  match = *bp++;  while (bp < limit) {    c = *bp++;    if (c == '\\') {      if (*bp++ == '\n' && count_newlines)	++ip->lineno;    } else if (c == '\n') {      bp -= 2;			/* whoa!  back up to eol and punt. */      break;    } else if (c == match)      break;  }  ip->bufp = bp;  return bp;}/* * write out a #line command, for instance, after an #include file. */staticoutput_line_command (ip, op)     FILE_BUF *ip, *op;{  int len, line_cmd_buf[500];  if (ip->fname == NULL)    return;#ifdef OUTPUT_LINE_COMMANDS  sprintf(line_cmd_buf, "#line %d \"%s\"\n", ip->lineno, ip->fname);#else  sprintf(line_cmd_buf, "# %d \"%s\"\n", ip->lineno, ip->fname);#endif  len = strlen(line_cmd_buf);  check_expand (op, len);  if (op->bufp > op->buf && op->bufp[-1] != '\n')	/* JF make sure */  	*op->bufp++ = '\n';  bcopy (line_cmd_buf, op->bufp, len);  op->bufp += len;}/* Expand a macro call.   HP points to the symbol that is the macro being called.   IP is the input source for reading the arguments of the macro.   Send the result of the expansion to OP.   EXCESS_NEWLINES_PTR points to an integer;   we increment that integer once for each newline swallowed   in the process of reading this macro call.  */macroexpand (hp, ip, op, excess_newlines_ptr)     HASHNODE *hp;     FILE_BUF *ip, *op;     int *excess_newlines_ptr;{  FILE_BUF *ip2;  int nargs;  DEFINITION *defn = hp->value.defn;  int newlines_found = 0;  /* it might not actually be a macro.  */  if (hp->type != T_MACRO)    return expand_special_symbol (hp, ip, op);  ip2 = &instack[indepth++];  bzero (ip2, sizeof (FILE_BUF)); /* paranoia */  nargs = defn->nargs;  if (nargs >= 0)    {      register U_CHAR *bp, *xbuf;      U_CHAR *skip_macro_argument ();      register int i;      int xbuf_len;      int offset;		/* offset in expansion,				   copied a piece at a time */      int totlen;		/* total amount of exp buffer filled so far */      register struct reflist *ap;      struct argptrs { 		       U_CHAR *argstart;		       int length;		     } *args;      args = (struct argptrs *) alloca ((nargs + 1) * sizeof (struct argptrs));      if (ip->bufp >= ip->buf+ip->length)	{			/* JF evil magic to make things work! */	  ip = &instack[indepth-3];	}      bp = ip->bufp;      /* make sure it really was a macro call. */      if (isspace(bp[-1])) {	while (isspace (*bp)) {	  if (*bp == '\n')	    ++newlines_found;	  bp++;	}	if (*bp != '(')	  goto nope;	bp++;			/* skip over the paren */      }      else if (*(bp-1) != '(')	goto nope;      for (i = 0; i < nargs; i++) {	args[i].argstart = bp;	bp = skip_macro_argument(bp, ip, &newlines_found);	args[i].length = bp - args[i].argstart;	if (*bp == ',')	  bp++;      }      args[nargs].argstart = bp;      if (*bp++ != ')')	goto nope;      /* make a rescan buffer with enough room for the pattern plus	 all the arg strings. */      xbuf_len = defn->length + 1;      for (ap = defn->pattern; ap != NULL; ap = ap->next)	xbuf_len += args[ap->argno - 1].length;      xbuf = (U_CHAR *) alloca (xbuf_len);      offset = totlen = 0;      for (ap = defn->pattern; ap != NULL; ap = ap->next) {	bcopy (defn->expansion + offset, xbuf + totlen, ap->nchars);	totlen += ap->nchars;	offset += ap->nchars;	if (ap->argno > 0) {	  bcopy (args[ap->argno - 1].argstart, xbuf + totlen,		 args[ap->argno - 1].length);	  totlen += args[ap->argno - 1].length;	}	if (totlen > xbuf_len)	  {	    /* impossible */	    error ("cpp impossible internal error: expansion too large");	    goto nope;		/* this can't happen??? */	  }      }      /* if there is anything left after handling the arg list,	 copy that in too. */      if (offset < defn->length) {	bcopy (defn->expansion + offset, xbuf + totlen,	       defn->length - offset);	totlen += defn->length - offset;      }

⌨️ 快捷键说明

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