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

📄 expand.c

📁 DSP网络驱动开发_TMS3206
💻 C
字号:
/* Variable expansion functions for GNU Make.Copyright (C) 1988, 89, 91, 92, 93, 95 Free Software Foundation, Inc.This file is part of GNU Make.GNU Make is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU Make is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Make; see the file COPYING.  If not, write tothe Free Software Foundation, Inc., 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "make.h"#include "filedef.h"#include "job.h"#include "commands.h"#include "variable.h"#include "rule.h"/* The next two describe the variable output buffer.   This buffer is used to hold the variable-expansion of a line of the   makefile.  It is made bigger with realloc whenever it is too small.   variable_buffer_length is the size currently allocated.   variable_buffer is the address of the buffer.   For efficiency, it's guaranteed that the buffer will always have   VARIABLE_BUFFER_ZONE extra bytes allocated.  This allows you to add a few   extra chars without having to call a function.  Note you should never use   these bytes unless you're _sure_ you have room (you know when the buffer   length was last checked.  */#define VARIABLE_BUFFER_ZONE    5static unsigned int variable_buffer_length;char *variable_buffer;/* Subroutine of variable_expand and friends:   The text to add is LENGTH chars starting at STRING to the variable_buffer.   The text is added to the buffer at PTR, and the updated pointer into   the buffer is returned as the value.  Thus, the value returned by   each call to variable_buffer_output should be the first argument to   the following call.  */char *variable_buffer_output (ptr, string, length)     char *ptr, *string;     unsigned int length;{  register unsigned int newlen = length + (ptr - variable_buffer);  if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length)    {      unsigned int offset = ptr - variable_buffer;      variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length				? newlen + 100				: 2 * variable_buffer_length);      variable_buffer = (char *) xrealloc (variable_buffer,					   variable_buffer_length);      ptr = variable_buffer + offset;    }  bcopy (string, ptr, length);  return ptr + length;}/* Return a pointer to the beginning of the variable buffer.  */static char *initialize_variable_output (){  /* If we don't have a variable output buffer yet, get one.  */  if (variable_buffer == 0)    {      variable_buffer_length = 200;      variable_buffer = (char *) xmalloc (variable_buffer_length);      variable_buffer[0] = '\0';    }  return variable_buffer;}/* Recursively expand V.  The returned string is malloc'd.  */char *recursively_expand (v)     register struct variable *v;{  char *value;  if (v->expanding)    /* Expanding V causes infinite recursion.  Lose.  */    fatal (reading_file,           _("Recursive variable `%s' references itself (eventually)"),           v->name);  v->expanding = 1;  value = allocated_variable_expand (v->value);  v->expanding = 0;  return value;}/* Warn that NAME is an undefined variable.  */#ifdef __GNUC____inline#endifstatic voidwarn_undefined (name, length)     char *name;     unsigned int length;{  if (warn_undefined_variables_flag)    error (reading_file,           _("warning: undefined variable `%.*s'"), (int)length, name);}/* Expand a simple reference to variable NAME, which is LENGTH chars long.  */#ifdef __GNUC____inline#endifstatic char *reference_variable (o, name, length)     char *o;     char *name;     unsigned int length;{  register struct variable *v = lookup_variable (name, length);  if (v == 0)    warn_undefined (name, length);  if (v != 0 && *v->value != '\0')    {      char *value = (v->recursive ? recursively_expand (v) : v->value);      o = variable_buffer_output (o, value, strlen (value));      if (v->recursive)	free (value);    }  return o;}/* Scan STRING for variable references and expansion-function calls.  Only   LENGTH bytes of STRING are actually scanned.  If LENGTH is -1, scan until   a null byte is found.   Write the results to LINE, which must point into `variable_buffer'.  If   LINE is NULL, start at the beginning of the buffer.   Return a pointer to LINE, or to the beginning of the buffer if LINE is   NULL.  */char *variable_expand_string (line, string, length)     register char *line;     char *string;     long length;{  register struct variable *v;  register char *p, *o, *p1;  char save_char = '\0';  unsigned int line_offset;  if (!line)    line = initialize_variable_output();  p = string;  o = line;  line_offset = line - variable_buffer;  if (length >= 0)    {      save_char = string[length];      string[length] = '\0';    }  while (1)    {      /* Copy all following uninteresting chars all at once to the         variable output buffer, and skip them.  Uninteresting chars end	 at the next $ or the end of the input.  */      p1 = index (p, '$');      o = variable_buffer_output (o, p, p1 != 0 ? p1 - p : strlen (p) + 1);      if (p1 == 0)	break;      p = p1 + 1;      /* Dispatch on the char that follows the $.  */      switch (*p)	{	case '$':	  /* $$ seen means output one $ to the variable output buffer.  */	  o = variable_buffer_output (o, p, 1);	  break;	case '(':	case '{':	  /* $(...) or ${...} is the general case of substitution.  */	  {	    char openparen = *p;	    char closeparen = (openparen == '(') ? ')' : '}';	    register char *beg = p + 1;	    int free_beg = 0;	    char *op, *begp;	    char *end, *colon;	    op = o;	    begp = p;	    if (handle_function (&op, &begp))	      {		o = op;		p = begp;		break;	      }	    /* Is there a variable reference inside the parens or braces?	       If so, expand it before expanding the entire reference.  */	    end = index (beg, closeparen);	    if (end == 0)              /* Unterminated variable reference.  */              fatal (reading_file, _("unterminated variable reference"));	    p1 = lindex (beg, end, '$');	    if (p1 != 0)	      {		/* BEG now points past the opening paren or brace.		   Count parens or braces until it is matched.  */		int count = 0;		for (p = beg; *p != '\0'; ++p)		  {		    if (*p == openparen)		      ++count;		    else if (*p == closeparen && --count < 0)		      break;		  }		/* If COUNT is >= 0, there were unmatched opening parens		   or braces, so we go to the simple case of a variable name		   such as `$($(a)'.  */		if (count < 0)		  {		    beg = expand_argument (beg, p); /* Expand the name.  */		    free_beg = 1; /* Remember to free BEG when finished.  */		    end = index (beg, '\0');		  }	      }	    else	      /* Advance P to the end of this reference.  After we are                 finished expanding this one, P will be incremented to                 continue the scan.  */	      p = end;	    /* This is not a reference to a built-in function and	       any variable references inside are now expanded.	       Is the resultant text a substitution reference?  */	    colon = lindex (beg, end, ':');	    if (colon != 0)	      {		/* This looks like a substitution reference: $(FOO:A=B).  */		char *subst_beg, *subst_end, *replace_beg, *replace_end;		subst_beg = colon + 1;		subst_end = index (subst_beg, '=');		if (subst_end == 0)		  /* There is no = in sight.  Punt on the substitution		     reference and treat this as a variable name containing		     a colon, in the code below.  */		  colon = 0;		else		  {		    replace_beg = subst_end + 1;		    replace_end = end;		    /* Extract the variable name before the colon		       and look up that variable.  */		    v = lookup_variable (beg, colon - beg);		    if (v == 0)		      warn_undefined (beg, colon - beg);		    if (v != 0 && *v->value != '\0')		      {			char *value = (v->recursive ? recursively_expand (v)				       : v->value);			char *pattern, *percent;			if (free_beg)			  {			    *subst_end = '\0';			    pattern = subst_beg;			  }			else			  {			    pattern = (char *) alloca (subst_end - subst_beg						       + 1);			    bcopy (subst_beg, pattern, subst_end - subst_beg);			    pattern[subst_end - subst_beg] = '\0';			  }			percent = find_percent (pattern);			if (percent != 0)			  {			    char *replace;			    if (free_beg)			      {				*replace_end = '\0';				replace = replace_beg;			      }			    else			      {				replace = (char *) alloca (replace_end							   - replace_beg							   + 1);				bcopy (replace_beg, replace,				       replace_end - replace_beg);				replace[replace_end - replace_beg] = '\0';			      }			    o = patsubst_expand (o, value, pattern, replace,						 percent, (char *) 0);			  }			else			  o = subst_expand (o, value,					    pattern, replace_beg,					    strlen (pattern),					    end - replace_beg,					    0, 1);			if (v->recursive)			  free (value);		      }		  }	      }	    if (colon == 0)	      /* This is an ordinary variable reference.		 Look up the value of the variable.  */		o = reference_variable (o, beg, end - beg);	  if (free_beg)	    free (beg);	  }	  break;	case '\0':	  break;	default:	  if (isblank (p[-1]))	    break;	  /* A $ followed by a random char is a variable reference:	     $a is equivalent to $(a).  */	  {	    /* We could do the expanding here, but this way	       avoids code repetition at a small performance cost.  */	    char name[5];	    name[0] = '$';	    name[1] = '(';	    name[2] = *p;	    name[3] = ')';	    name[4] = '\0';	    p1 = allocated_variable_expand (name);	    o = variable_buffer_output (o, p1, strlen (p1));	    free (p1);	  }	  break;	}      if (*p == '\0')	break;      else	++p;    }  if (save_char)    string[length] = save_char;  (void)variable_buffer_output (o, "", 1);  return (variable_buffer + line_offset);}/* Scan LINE for variable references and expansion-function calls.   Build in `variable_buffer' the result of expanding the references and calls.   Return the address of the resulting string, which is null-terminated   and is valid only until the next time this function is called.  */char *variable_expand (line)     char *line;{  return variable_expand_string(NULL, line, (long)-1);}/* Expand an argument for an expansion function.   The text starting at STR and ending at END is variable-expanded   into a null-terminated string that is returned as the value.   This is done without clobbering `variable_buffer' or the current   variable-expansion that is in progress.  */char *expand_argument (str, end)     char *str, *end;{  char *tmp;  if (*end == '\0')    tmp = str;  else    {      tmp = (char *) alloca (end - str + 1);      bcopy (str, tmp, end - str);      tmp[end - str] = '\0';    }  return allocated_variable_expand (tmp);}/* Expand LINE for FILE.  Error messages refer to the file and line where   FILE's commands were found.  Expansion uses FILE's variable set list.  */static char *variable_expand_for_file (line, file)     char *line;     register struct file *file;{  char *result;  struct variable_set_list *save, *fnext;  if (file == 0)    return variable_expand (line);  save = current_variable_set_list;  current_variable_set_list = file->variables;  if (file->cmds && file->cmds->fileinfo.filenm)    reading_file = &file->cmds->fileinfo;  else    reading_file = 0;  fnext = file->variables->next;  /* See if there's a pattern-specific variable struct for this target.  */  if (!file->pat_searched)    {      file->patvar = lookup_pattern_var(file->name);      file->pat_searched = 1;    }  if (file->patvar != 0)    {      file->patvar->vars->next = fnext;      file->variables->next = file->patvar->vars;    }  result = variable_expand (line);  current_variable_set_list = save;  reading_file = 0;  file->variables->next = fnext;  return result;}/* Like variable_expand_for_file, but the returned string is malloc'd.   This function is called a lot.  It wants to be efficient.  */char *allocated_variable_expand_for_file (line, file)     char *line;     struct file *file;{  char *value;  char *obuf = variable_buffer;  unsigned int olen = variable_buffer_length;  variable_buffer = 0;  value = variable_expand_for_file (line, file);#if 0  /* Waste a little memory and save time.  */  value = xrealloc (value, strlen (value))#endif  variable_buffer = obuf;  variable_buffer_length = olen;  return value;}

⌨️ 快捷键说明

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