home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / MAK358AS.ZIP / EXPAND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-22  |  9.3 KB  |  362 lines

  1. /* Variable expansion functions for GNU Make.
  2. Copyright (C) 1988, 1989 Free Software Foundation, Inc.
  3. This file is part of GNU Make.
  4.  
  5. GNU Make is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 1, or (at your option)
  8. any later version.
  9.  
  10. GNU Make is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with GNU Make; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /*
  20.  * MS-DOS port (c) 1990 by Thorsten Ohl <ohl@gnu.ai.mit.edu>
  21.  *
  22.  * To this port, the same copying conditions apply as to the
  23.  * original release.
  24.  *
  25.  * IMPORTANT:
  26.  * This file is not identical to the original GNU release!
  27.  * You should have received this code as patch to the official
  28.  * GNU release.
  29.  *
  30.  * MORE IMPORTANT:
  31.  * This port comes with ABSOLUTELY NO WARRANTY.
  32.  *
  33.  * $Header: e:/gnu/make/RCS/expand.c'v 3.58.0.1 90/07/17 00:59:05 tho Exp $
  34.  */
  35.  
  36. #include "make.h"
  37. #include "commands.h"
  38. #include "file.h"
  39. #include "variable.h"
  40.  
  41. #ifdef MSDOS
  42. static  char *recursively_expand (struct variable *v);
  43. #endif /* MSDOS */
  44.  
  45. /* Recursively expand V.  The returned string is malloc'd.  */
  46.  
  47. static char *
  48. recursively_expand (v)
  49.      register struct variable *v;
  50. {
  51.   char *value;
  52.  
  53.   if (v->expanding)
  54.     fatal ("%s:%u: Recursive variable `%s' references itself (eventually)",
  55.        reading_filename, *reading_lineno_ptr, v->name);
  56.  
  57.   v->expanding = 1;
  58.   value = allocated_variable_expand (v->value);
  59.   v->expanding = 0;
  60.  
  61.   return value;
  62. }
  63.  
  64. /* Scan LINE for variable references and expansion-function calls.
  65.    Build in `variable_buffer' the result of expanding the references and calls.
  66.    Return the address of the resulting string, which is null-terminated
  67.    and is valid only until the next time this function is called.  */
  68.  
  69. char *
  70. variable_expand (line)
  71.      register char *line;
  72. {
  73.   register struct variable *v;
  74.   register char *p, *o, *p1;
  75.  
  76.   p = line;
  77.   o = initialize_variable_output ();
  78.  
  79.   while (1)
  80.     {
  81.       /* Copy all following uninteresting chars all at once to the
  82.          variable output buffer, and skip them.  Uninteresting chars end
  83.      at the next $ or the end of the input.  */
  84.  
  85.       p1 = index (p, '$');
  86.  
  87.       o = variable_buffer_output (o, p, p1 != 0 ? p1 - p : strlen (p) + 1);
  88.  
  89.       if (p1 == 0)
  90.     break;
  91.       p = p1 + 1;
  92.  
  93.       /* Dispatch on the char that follows the $.  */
  94.  
  95.       switch (*p)
  96.     {
  97.     case '$':
  98.       /* $$ seen means output one $ to the variable output buffer.  */
  99.       o = variable_buffer_output (o, p, 1);
  100.       break;
  101.  
  102.     case '(':
  103.     case '{':
  104.       /* $(...) or ${...} is the general case of substitution.  */
  105.       {
  106.         char openparen = *p;
  107.         char closeparen = (openparen == '(') ? ')' : '}';
  108.         register char *beg = p + 1;
  109.         char *op, *begp;
  110.         char *end;
  111.  
  112.         op = o;
  113.         begp = p;
  114.         if (handle_function (&op, &begp))
  115.           {
  116.         o = op;
  117.         p = begp;
  118.         break;
  119.           }
  120.  
  121.         /* Is there a variable reference inside the parens or braces?
  122.            If so, expand it before expanding the entire reference.  */
  123.  
  124.         p1 = index (beg, closeparen);
  125.         if (p1 != 0)
  126.           p1 = lindex (beg, p1, '$');
  127.         if (p1 != 0)
  128.           {
  129.         /* BEG now points past the opening paren or brace.
  130.            Count parens or braces until it is matched.  */
  131.         int count = 0;
  132.         for (p = beg; *p != '\0'; ++p)
  133.           {
  134.             if (*p == openparen)
  135.               ++count;
  136.             else if (*p == closeparen && --count < 0)
  137.               break;
  138.           }
  139.         /* If count is >= 0, there were unmatched opening parens
  140.            or braces, so we go to the simple case of a variable name
  141.            such as `$($(a)'.  */
  142.         if (count < 0)
  143.           {
  144.             char *name = expand_argument (beg, p);
  145.             static char start[3] = { '$', }, end[2];
  146.             start[1] = openparen;
  147.             end[0] = closeparen;
  148.             p1 = concat (start, name, end);
  149.             free (name);
  150.             name = allocated_variable_expand (p1);
  151.             o = variable_buffer_output (o, name, strlen (name));
  152.             free (name);
  153.             break;
  154.           }
  155.           }
  156.  
  157.         /* This is not a reference to a built-in function and
  158.            it does not contain any variable references inside.
  159.            There are several things it could be.  */
  160.  
  161.         p = index (beg, ':');
  162.         if (p != 0 && lindex (beg, p, closeparen) == 0)
  163.           {
  164.         /* This is a substitution reference: $(FOO:A=B).  */
  165.         int count;
  166.         char *subst_beg, *replace_beg;
  167.         unsigned int subst_len, replace_len;
  168.  
  169.         v = lookup_variable (beg, p - beg);
  170.  
  171.         subst_beg = p + 1;
  172.         count = 0;
  173.         for (p = subst_beg; *p != '\0'; ++p)
  174.           {
  175.             if (*p == openparen)
  176.               ++count;
  177.             else if (*p == closeparen)
  178.               --count;
  179.             else if (*p == '=' && count <= 0)
  180.               break;
  181.           }
  182.         if (count > 0)
  183.           /* There were unmatched opening parens.  */
  184.           return initialize_variable_output ();
  185.         subst_len = p - subst_beg;
  186.  
  187.         replace_beg = p + 1;
  188.         count = 0;
  189.         for (p = replace_beg; *p != '\0'; ++p)
  190.           {
  191.             if (*p == openparen)
  192.               ++count;
  193.             else if (*p == closeparen && --count < 0)
  194.               break;
  195.           }
  196.         if (count > 0)
  197.           /* There were unmatched opening parens.  */
  198.           return initialize_variable_output ();
  199.         end = p;
  200.         replace_len = p - replace_beg;
  201.  
  202.         if (v != 0 && *v->value != '\0')
  203.           {
  204.             char *value = (v->recursive ? recursively_expand (v)
  205.                    : v->value);
  206.             if (lindex (subst_beg, subst_beg + subst_len, '%') != 0)
  207.               {
  208.             p = savestring (subst_beg, subst_len);
  209.             p1 = savestring (replace_beg, replace_len);
  210.             o = patsubst_expand (o, value, p, p1,
  211.                          index (p, '%'), index (p1, '%'));
  212.             free (p);
  213.             free (p1);
  214.               }
  215.             else
  216.               o = subst_expand (o, value, subst_beg, replace_beg,
  217.                     subst_len, replace_len, 0, 1);
  218.             if (v->recursive)
  219.               free (value);
  220.           }
  221.           }
  222.  
  223.         /* No, this must be an ordinary variable reference.  */
  224.         else
  225.           {
  226.         /* Look up the value of the variable.  */
  227.         end = index (beg, closeparen);
  228.         if (end == 0)
  229.           return initialize_variable_output ();
  230.         v = lookup_variable (beg, end - beg);
  231.  
  232.         if (v != 0 && *v->value != '\0')
  233.           {
  234.             char *value = (v->recursive ? recursively_expand (v)
  235.                    : v->value);
  236.             o = variable_buffer_output (o, value, strlen (value));
  237.             if (v->recursive)
  238.               free (value);
  239.           }
  240.           }
  241.  
  242.         /* Advance p past the variable reference to resume scan.  */
  243.         p = end;
  244.       }
  245.       break;
  246.  
  247.     case '\0':
  248.     case '\t':
  249.     case ' ':
  250.       break;
  251.  
  252.     default:
  253.       /* A $ followed by a random char is a variable reference:
  254.          $a is equivalent to $(a).  */
  255.       {
  256.         /* We could do the expanding here, but this way
  257.            avoids code repetition at a small performance cost.  */
  258.         char name[5];
  259.         name[0] = '$';
  260.         name[1] = '(';
  261.         name[2] = *p;
  262.         name[3] = ')';
  263.         name[4] = '\0';
  264.         p1 = allocated_variable_expand (name);
  265.         o = variable_buffer_output (o, p1, strlen (p1));
  266.         free (p1);
  267.       }
  268.  
  269.       break;
  270.     }      
  271.  
  272.       if (*p == '\0')
  273.     break;
  274.       else
  275.     ++p;
  276.     }
  277.  
  278.   (void) variable_buffer_output (o, "", 1);
  279.   return initialize_variable_output ();
  280. }
  281.  
  282. /* Expand an argument for an expansion function.
  283.    The text starting at STR and ending at END is variable-expanded
  284.    into a null-terminated string that is returned as the value.
  285.    This is done without clobbering `variable_buffer' or the current
  286.    variable-expansion that is in progress.  */
  287.  
  288. char *
  289. expand_argument (str, end)
  290.      char *str, *end;
  291. {
  292.   char *tmp = savestring (str, end - str);
  293.   char *value = allocated_variable_expand (tmp);
  294.  
  295.   free (tmp);
  296.  
  297.   return value;
  298. }
  299.  
  300. /* Expand LINE for FILE.  Error messages refer to the file and line where
  301.    FILE's commands were found.  Expansion uses FILE's variable set list.  */
  302.  
  303. char *
  304. variable_expand_for_file (line, file)
  305.      char *line;
  306.      register struct file *file;
  307. {
  308.   char *result;
  309.   struct variable_set_list *save;
  310.  
  311.   if (file == 0)
  312.     return variable_expand (line);
  313.  
  314.   save = current_variable_set_list;
  315.   current_variable_set_list = file->variables;
  316.   reading_filename = file->cmds->filename;
  317.   reading_lineno_ptr = &file->cmds->lineno;
  318.   result = variable_expand (line);
  319.   current_variable_set_list = save;
  320.   reading_filename = 0;
  321.   reading_lineno_ptr = 0;
  322.  
  323.   return result;
  324. }
  325.  
  326. /* Like variable_expand, but the returned string is malloc'd.  */
  327. char *
  328. allocated_variable_expand (line)
  329.      char *line;
  330. {
  331. #ifdef MSDOS
  332.   return allocated_var_exp_for_file (line, (struct file *) 0);
  333. #else
  334.   return allocated_variable_expand_for_file (line, (struct file *) 0);
  335. #endif /* MSDOS */
  336.  
  337. }
  338.  
  339. /* Like variable_expand_for_file, but the returned string is malloc'd.  */
  340.  
  341. char *
  342. #ifdef MSDOS
  343. allocated_var_exp_for_file (line, file)
  344. #else
  345. allocated_variable_expand_for_file (line, file)
  346. #endif /* MSDOS */
  347.      char *line;
  348.      struct file *file;
  349. {
  350.   char *save;
  351.   char *value;
  352.  
  353.   save = save_variable_output ();
  354.  
  355.   value = variable_expand_for_file (line, file);
  356.   value = savestring (value, strlen (value));
  357.  
  358.   restore_variable_output (save);
  359.  
  360.   return value;
  361. }
  362.