1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  *      read.c
  28  *
  29  *      This file contains the makefile reader.
  30  */
  31 
  32 /*
  33  * Included files
  34  */
  35 #include <alloca.h>               /* alloca() */
  36 #include <errno.h>                /* errno */
  37 #include <fcntl.h>                /* fcntl() */
  38 #include <mk/defs.h>
  39 #include <mksh/macro.h>           /* expand_value(), expand_macro() */
  40 #include <mksh/misc.h>            /* getmem() */
  41 #include <mksh/read.h>            /* get_next_block_fn() */
  42 #include <sys/uio.h>              /* read() */
  43 #include <unistd.h>               /* read(), unlink() */
  44 #include <libintl.h>
  45 
  46 
  47 /*
  48  * typedefs & structs
  49  */
  50 
  51 /*
  52  * Static variables
  53  */
  54 
  55 static int line_started_with_space=0; // Used to diagnose spaces instead of tabs
  56 
  57 /*
  58  * File table of contents
  59  */
  60 static  void            parse_makefile(register Name true_makefile_name, register Source source);
  61 static  Source          push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source);
  62 extern  void            enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen);
  63 extern  Name            normalize_name(register wchar_t *name_string, register int length);
  64 
  65 /*
  66  *      read_simple_file(makefile_name, chase_path, doname_it,
  67  *               complain, must_exist, report_file, lock_makefile)
  68  *
  69  *      Make the makefile and setup to read it. Actually read it if it is stdio
  70  *
  71  *      Return value:
  72  *                              false if the read failed
  73  *
  74  *      Parameters:
  75  *              makefile_name   Name of the file to read
  76  *              chase_path      Use the makefile path when opening file
  77  *              doname_it       Call doname() to build the file first
  78  *              complain        Print message if doname/open fails
  79  *              must_exist      Generate fatal if file is missing
  80  *              report_file     Report file when running -P
  81  *              lock_makefile   Lock the makefile when reading
  82  *
  83  *      Static variables used:
  84  *
  85  *      Global variables used:
  86  *              do_not_exec_rule Is -n on?
  87  *              file_being_read Set to the name of the new file
  88  *              line_number     The number of the current makefile line
  89  *              makefiles_used  A list of all makefiles used, appended to
  90  */
  91 
  92 
  93 Boolean
  94 read_simple_file(register Name makefile_name, register Boolean chase_path, register Boolean doname_it, Boolean complain, Boolean must_exist, Boolean report_file, Boolean lock_makefile)
  95 {
  96         static short            max_include_depth;
  97         register Property       makefile = maybe_append_prop(makefile_name,
  98                                                              makefile_prop);
  99         Boolean                 forget_after_parse = false;
 100         static pathpt           makefile_path;
 101         register int            n;
 102         char                    *path;
 103         register Source         source = ALLOC(Source);
 104         Property                orig_makefile = makefile;
 105         Dependency              *dpp;
 106         Dependency              dp;
 107         register int            length;
 108         wchar_t                 *previous_file_being_read = file_being_read;
 109         int                     previous_line_number = line_number;
 110         wchar_t                 previous_current_makefile[MAXPATHLEN];
 111         Makefile_type           save_makefile_type;
 112         Name                    normalized_makefile_name;
 113         register wchar_t        *string_start;
 114         register wchar_t        *string_end;
 115 
 116 
 117 
 118         wchar_t * wcb = get_wstring(makefile_name->string_mb);
 119 
 120         if (max_include_depth++ >= 40) {
 121                 fatal(gettext("Too many nested include statements"));
 122         }
 123         if (makefile->body.makefile.contents != NULL) {
 124                 retmem(makefile->body.makefile.contents);
 125         }
 126         source->inp_buf =
 127           source->inp_buf_ptr =
 128             source->inp_buf_end = NULL;
 129         source->error_converting = false;
 130         makefile->body.makefile.contents = NULL;
 131         makefile->body.makefile.size = 0;
 132         if ((makefile_name->hash.length != 1) ||
 133             (wcb[0] != (int) hyphen_char)) {
 134                 if ((makefile->body.makefile.contents == NULL) &&
 135                     (doname_it)) {
 136                         if (makefile_path == NULL) {
 137                                 char *pfx = make_install_prefix();
 138                                 char *path;
 139 
 140                                 add_dir_to_path(".",
 141                                                 &makefile_path,
 142                                                 -1);
 143 
 144                                 // As regularly installed
 145                                 asprintf(&path, "%s/../share/lib/make", pfx);
 146                                 add_dir_to_path(path, &makefile_path, -1);
 147                                 free(path);
 148 
 149                                 // Tools build
 150                                 asprintf(&path, "%s/../../share/", pfx);
 151                                 add_dir_to_path(path, &makefile_path, -1);
 152                                 free(path);
 153                                     
 154                                 add_dir_to_path("/usr/share/lib/make",
 155                                                 &makefile_path,
 156                                                 -1);
 157                                 add_dir_to_path("/etc/default",
 158                                                 &makefile_path,
 159                                                 -1);
 160 
 161                                 free(pfx);
 162                         }
 163                         save_makefile_type = makefile_type;
 164                         makefile_type = reading_nothing;
 165                         if (doname(makefile_name, true, false) == build_dont_know) {
 166                                 /* Try normalized filename */
 167                                 string_start=get_wstring(makefile_name->string_mb);
 168                                 for (string_end=string_start+1; *string_end != L'\0'; string_end++);
 169                                 normalized_makefile_name=normalize_name(string_start, string_end - string_start);
 170                                 if ((strcmp(makefile_name->string_mb, normalized_makefile_name->string_mb) == 0) || 
 171                                         (doname(normalized_makefile_name, true, false) == build_dont_know)) {
 172                                         n = access_vroot(makefile_name->string_mb,
 173                                                  4,
 174                                                  chase_path ?
 175                                                  makefile_path : NULL,
 176                                                  VROOT_DEFAULT);
 177                                         if (n == 0) {
 178                                                 get_vroot_path((char **) NULL,
 179                                                        &path,
 180                                                        (char **) NULL);
 181                                                 if ((path[0] == (int) period_char) &&
 182                                                     (path[1] == (int) slash_char)) {
 183                                                         path += 2;
 184                                                 }
 185                                                 MBSTOWCS(wcs_buffer, path);
 186                                                 makefile_name = GETNAME(wcs_buffer,
 187                                                                 FIND_LENGTH);
 188                                         }
 189                                 }
 190                                 retmem(string_start);
 191                                 /* 
 192                                  * Commented out: retmem_mb(normalized_makefile_name->string_mb);
 193                                  * We have to return this memory, but it seems to trigger a bug
 194                                  * in dmake or in Sun C++ 5.7 compiler (it works ok if this code
 195                                  * is compiled using Sun C++ 5.6).
 196                                  */
 197                                 // retmem_mb(normalized_makefile_name->string_mb); 
 198                         }
 199                         makefile_type = save_makefile_type;
 200                 }
 201                 source->string.free_after_use = false;
 202                 source->previous = NULL;
 203                 source->already_expanded = false;
 204                 /* Lock the file for read, but not when -n. */
 205                 if (lock_makefile && 
 206                     !do_not_exec_rule) {
 207 
 208                          make_state_lockfile = getmem(strlen(make_state->string_mb) + strlen(".lock") + 1);
 209                          (void) sprintf(make_state_lockfile,
 210                                                 "%s.lock",
 211                                                 make_state->string_mb);
 212                         (void) file_lock(make_state->string_mb,
 213                                          make_state_lockfile,
 214                                          (int *) &make_state_locked,
 215                                          0);
 216                         if(!make_state_locked) {
 217                                 printf("-- NO LOCKING for read\n");
 218                                 retmem_mb(make_state_lockfile);
 219                                 make_state_lockfile = 0;
 220                                 return failed;
 221                         }
 222                 }
 223                 if (makefile->body.makefile.contents == NULL) {
 224                         save_makefile_type = makefile_type;
 225                         makefile_type = reading_nothing;
 226                         if ((doname_it) &&
 227                             (doname(makefile_name, true, false) == build_failed)) {
 228                                 if (complain) {
 229                                         (void) fprintf(stderr,
 230                                                        gettext("%s: Couldn't make `%s'\n"),
 231                                                        getprogname(),
 232                                                        makefile_name->string_mb);
 233                                 }
 234                                 max_include_depth--;
 235                                 makefile_type = save_makefile_type;
 236                                 return failed;
 237                         }
 238                         makefile_type = save_makefile_type;
 239                         //
 240                         // Before calling exists() make sure that we have the right timestamp
 241                         //
 242                         makefile_name->stat.time = file_no_time;
 243 
 244                         if (exists(makefile_name) == file_doesnt_exist) {
 245                                 if (complain ||
 246                                     (makefile_name->stat.stat_errno != ENOENT)) {
 247                                         if (must_exist) {
 248                                                 fatal(gettext("Can't find `%s': %s"),
 249                                                       makefile_name->string_mb,
 250                                                       errmsg(makefile_name->
 251                                                              stat.stat_errno));
 252                                         } else {
 253                                                 warning(gettext("Can't find `%s': %s"),
 254                                                         makefile_name->string_mb,
 255                                                         errmsg(makefile_name->
 256                                                                stat.stat_errno));
 257                                         }
 258                                 }
 259                                 max_include_depth--;
 260                                 if(make_state_locked && (make_state_lockfile != NULL)) {
 261                                         (void) unlink(make_state_lockfile);
 262                                         retmem_mb(make_state_lockfile);
 263                                         make_state_lockfile = NULL;
 264                                         make_state_locked = false;
 265                                 }
 266                                 retmem(wcb);
 267                                 retmem_mb((char *)source);
 268                                 return failed;
 269                         }
 270                         /*
 271                          * These values are the size and bytes of
 272                          * the MULTI-BYTE makefile.
 273                          */
 274                         orig_makefile->body.makefile.size =
 275                           makefile->body.makefile.size =
 276                             source->bytes_left_in_file =
 277                               makefile_name->stat.size;
 278                         if (report_file) {
 279                                 for (dpp = &makefiles_used;
 280                                      *dpp != NULL;
 281                                      dpp = &(*dpp)->next);
 282                                 dp = ALLOC(Dependency);
 283                                 dp->next = NULL;
 284                                 dp->name = makefile_name;
 285                                 dp->automatic = false;
 286                                 dp->stale = false;
 287                                 dp->built = false;
 288                                 *dpp = dp;
 289                         }
 290                         source->fd = open_vroot(makefile_name->string_mb,
 291                                                 O_RDONLY,
 292                                                 0,
 293                                                 NULL,
 294                                                 VROOT_DEFAULT);
 295                         if (source->fd < 0) {
 296                                 if (complain || (errno != ENOENT)) {
 297                                         if (must_exist) {
 298                                                 fatal(gettext("Can't open `%s': %s"),
 299                                                       makefile_name->string_mb,
 300                                                       errmsg(errno));
 301                                         } else {
 302                                                 warning(gettext("Can't open `%s': %s"),
 303                                                         makefile_name->string_mb,
 304                                                         errmsg(errno));
 305                                         }
 306                                 }
 307                                 max_include_depth--;
 308                                 return failed;
 309                         }
 310                         (void) fcntl(source->fd, F_SETFD, 1);
 311                         orig_makefile->body.makefile.contents =
 312                           makefile->body.makefile.contents =
 313                             source->string.text.p =
 314                               source->string.buffer.start =
 315                                 ALLOC_WC((int) (makefile_name->stat.size + 2));
 316                         if (makefile_type == reading_cpp_file) {
 317                                 forget_after_parse = true;
 318                         }
 319                         source->string.text.end = source->string.text.p;
 320                         source->string.buffer.end =
 321                           source->string.text.p + makefile_name->stat.size;
 322                 } else {
 323                         /* Do we ever reach here? */
 324                         source->fd = -1;
 325                         source->string.text.p =
 326                           source->string.buffer.start =
 327                             makefile->body.makefile.contents;
 328                         source->string.text.end =
 329                           source->string.buffer.end =
 330                             source->string.text.p + makefile->body.makefile.size;
 331                         source->bytes_left_in_file =
 332                           makefile->body.makefile.size;
 333                 }
 334                 file_being_read = wcb;
 335         } else {
 336                 char            *stdin_text_p;
 337                 char            *stdin_text_end;
 338                 char            *stdin_buffer_start;
 339                 char            *stdin_buffer_end;
 340                 char            *p_mb;
 341                 int             num_mb_chars;
 342                 size_t          num_wc_chars;
 343 
 344                 MBSTOWCS(wcs_buffer, "Standard in");
 345                 makefile_name = GETNAME(wcs_buffer, FIND_LENGTH);
 346                 /*
 347                  * Memory to read standard in, then convert it
 348                  * to wide char strings.
 349                  */
 350                 stdin_buffer_start =
 351                   stdin_text_p = getmem(length = 1024);
 352                 stdin_buffer_end = stdin_text_p + length;
 353                 MBSTOWCS(wcs_buffer, "standard input");
 354                 file_being_read = (wchar_t *) wsdup(wcs_buffer);
 355                 line_number = 0;
 356                 while ((n = read(fileno(stdin),
 357                                  stdin_text_p,
 358                                  length)) > 0) {
 359                         length -= n;
 360                         stdin_text_p += n;
 361                         if (length == 0) {
 362                                 p_mb = getmem(length = 1024 +
 363                                               (stdin_buffer_end -
 364                                                stdin_buffer_start));
 365                                 (void) strncpy(p_mb,
 366                                                stdin_buffer_start,
 367                                                (stdin_buffer_end -
 368                                                 stdin_buffer_start));
 369                                 retmem_mb(stdin_buffer_start);
 370                                 stdin_text_p = p_mb +
 371                                   (stdin_buffer_end - stdin_buffer_start);
 372                                 stdin_buffer_start = p_mb;
 373                                 stdin_buffer_end =
 374                                   stdin_buffer_start + length;
 375                                 length = 1024;
 376                         }
 377                 }
 378                 if (n < 0) {
 379                         fatal(gettext("Error reading standard input: %s"),
 380                               errmsg(errno));
 381                 }
 382                 stdin_text_p = stdin_buffer_start;
 383                 stdin_text_end = stdin_buffer_end - length;
 384                 num_mb_chars = stdin_text_end - stdin_text_p;
 385 
 386                 /*
 387                  * Now, convert the sequence of multibyte chars into
 388                  * a sequence of corresponding wide character codes.
 389                  */
 390                 source->string.free_after_use = false;
 391                 source->previous = NULL;
 392                 source->bytes_left_in_file = 0;
 393                 source->fd = -1;
 394                 source->already_expanded = false;
 395                 source->string.buffer.start =
 396                   source->string.text.p = ALLOC_WC(num_mb_chars + 1);
 397                 source->string.buffer.end =
 398                     source->string.text.p + num_mb_chars;
 399                 num_wc_chars = mbstowcs(source->string.text.p,
 400                                         stdin_text_p,
 401                                         num_mb_chars);
 402                 if ((int) num_wc_chars >= 0) {
 403                         source->string.text.end =
 404                           source->string.text.p + num_wc_chars;
 405                 }
 406                 (void) retmem_mb(stdin_text_p);
 407         }
 408         line_number = 1;
 409         if (trace_reader) {
 410                 (void) printf(gettext(">>>>>>>>>>>>>>>> Reading makefile %s\n"),
 411                               makefile_name->string_mb);
 412         }
 413         parse_makefile(makefile_name, source);
 414         if (trace_reader) {
 415                 (void) printf(gettext(">>>>>>>>>>>>>>>> End of makefile %s\n"),
 416                               makefile_name->string_mb);
 417         }
 418         if(file_being_read) {
 419                 retmem(file_being_read);
 420         }
 421         file_being_read = previous_file_being_read;
 422         line_number = previous_line_number;
 423         makefile_type = reading_nothing;
 424         max_include_depth--;
 425         if (make_state_locked) {
 426                 /* Unlock .make.state. */
 427                 unlink(make_state_lockfile);
 428                 make_state_locked = false;
 429                 retmem_mb(make_state_lockfile);
 430         }
 431         if (forget_after_parse) {
 432                 retmem(makefile->body.makefile.contents);
 433                 makefile->body.makefile.contents = NULL;
 434         }
 435         retmem_mb((char *)source);
 436         return succeeded;
 437 }
 438 
 439 /*
 440  *      parse_makefile(true_makefile_name, source)
 441  *
 442  *      Strings are read from Sources.
 443  *      When macros are found, their values are represented by a
 444  *      Source that is pushed on a stack. At end of string
 445  *      (that is returned from GET_CHAR() as 0), the block is popped.
 446  *
 447  *      Parameters:
 448  *              true_makefile_name      The name of makefile we are parsing
 449  *              source                  The source block to read from
 450  *
 451  *      Global variables used:
 452  *              do_not_exec_rule Is -n on?
 453  *              line_number     The number of the current makefile line
 454  *              makefile_type   What kind of makefile are we reading?
 455  *              empty_name      The Name ""
 456  */
 457 static void
 458 parse_makefile(register Name true_makefile_name, register Source source)
 459 {
 460 /*
 461         char                    mb_buffer[MB_LEN_MAX];
 462  */
 463         register wchar_t        *source_p;
 464         register wchar_t        *source_end;
 465         register wchar_t        *string_start;
 466         wchar_t                 *string_end;
 467         register Boolean        macro_seen_in_string;
 468         Boolean                 append;
 469         String_rec              name_string;
 470         wchar_t                 name_buffer[STRING_BUFFER_LENGTH];
 471         register int            distance;
 472         register int            paren_count;
 473         int                     brace_count;
 474         int                     char_number;
 475         Cmd_line                command;
 476         Cmd_line                command_tail;
 477         Name                    macro_value;
 478 
 479         Name_vector_rec         target;
 480         Name_vector_rec         depes;
 481         Name_vector_rec         extra_name_vector;
 482         Name_vector             current_names;
 483         Name_vector             extra_names = &extra_name_vector;
 484         Name_vector             nvp;
 485         Boolean                 target_group_seen;
 486 
 487         register Reader_state   state;
 488         register Reader_state   on_eoln_state;
 489         register Separator      separator;
 490 
 491         wchar_t                 buffer[4 * STRING_BUFFER_LENGTH];
 492         Source                  extrap;
 493 
 494         Boolean                 save_do_not_exec_rule = do_not_exec_rule;
 495         Name                    makefile_name;
 496 
 497         static Name             sh_name;
 498         static Name             shell_name;
 499         int                     i;
 500 
 501         static wchar_t          include_space[10];
 502         static wchar_t          include_tab[10];
 503         int                     tmp_bytes_left_in_string;
 504         Boolean                 tmp_maybe_include = false;
 505         int                     emptycount = 0;
 506         Boolean                 first_target;
 507 
 508         String_rec              include_name;
 509         wchar_t                 include_buffer[STRING_BUFFER_LENGTH];
 510 
 511         target.next = depes.next = NULL;
 512         /* Move some values from their struct to register declared locals */
 513         CACHE_SOURCE(0);
 514 
 515  start_new_line:
 516         /*
 517          * Read whitespace on old line. Leave pointer on first char on
 518          * next line.
 519          */
 520         first_target = true;
 521         on_eoln_state = exit_state;
 522 /*
 523         for (WCTOMB(mb_buffer, GET_CHAR());
 524              1;
 525              source_p++, WCTOMB(mb_buffer, GET_CHAR()))
 526                 switch (mb_buffer[0]) {
 527  */
 528         for (char_number=0; 1; source_p++,char_number++) switch (GET_CHAR()) {
 529         case nul_char:
 530                 /* End of this string. Pop it and return to the previous one */
 531                 GET_NEXT_BLOCK(source);
 532                 source_p--;
 533                 if (source == NULL) {
 534                         GOTO_STATE(on_eoln_state);
 535                 }
 536                 break;
 537         case newline_char:
 538         end_of_line:
 539                 source_p++;
 540                 if (source->fd >= 0) {
 541                         line_number++;
 542                 }
 543                 switch (GET_CHAR()) {
 544                 case nul_char:
 545                         GET_NEXT_BLOCK(source);
 546                         if (source == NULL) {
 547                                 GOTO_STATE(on_eoln_state);
 548                         }
 549                         /* Go back to the top of this loop */
 550                         goto start_new_line;
 551                 case newline_char:
 552                 case numbersign_char:
 553                 case dollar_char:
 554                 case space_char:
 555                 case tab_char:
 556                         /*
 557                          * Go back to the top of this loop since the
 558                          * new line does not start with a regular char.
 559                          */
 560                         goto start_new_line;
 561                 default:
 562                         /* We found the first proper char on the new line */
 563                         goto start_new_line_no_skip;
 564                 }
 565         case space_char:
 566                 if (char_number == 0)
 567                         line_started_with_space=line_number;
 568         case tab_char:
 569                 /* Whitespace. Just keep going in this loop */
 570                 break;
 571         case numbersign_char:
 572                 /* Comment. Skip over it */
 573                 for (; 1; source_p++) {
 574                         switch (GET_CHAR()) {
 575                         case nul_char:
 576                                 GET_NEXT_BLOCK_NOCHK(source);
 577                                 if (source == NULL) {
 578                                         GOTO_STATE(on_eoln_state);
 579                                 }
 580                                 if (source->error_converting) {
 581                                 // Illegal byte sequence - skip its first byte
 582                                         source->inp_buf_ptr++;
 583                                 }
 584                                 source_p--;
 585                                 break;
 586                         case backslash_char:
 587                                 /* Comments can be continued */
 588                                 if (*++source_p == (int) nul_char) {
 589                                         GET_NEXT_BLOCK_NOCHK(source);
 590                                         if (source == NULL) {
 591                                                 GOTO_STATE(on_eoln_state);
 592                                         }
 593                                         if (source->error_converting) {
 594                                         // Illegal byte sequence - skip its first byte
 595                                                 source->inp_buf_ptr++;
 596                                                 source_p--;
 597                                                 break;
 598                                         }
 599                                 }
 600                                 if(*source_p == (int) newline_char) {
 601                                         if (source->fd >= 0) {
 602                                                 line_number++;
 603                                         }
 604                                 }
 605                                 break;
 606                         case newline_char:
 607                                 /*
 608                                  * After we skip the comment we go to
 609                                  * the end of line handler since end of
 610                                  * line terminates comments.
 611                                  */
 612                                 goto end_of_line;
 613                         }
 614                 }
 615         case dollar_char:
 616                 /* Macro reference */
 617                 if (source->already_expanded) {
 618                         /*
 619                          * If we are reading from the expansion of a
 620                          * macro we already expanded everything enough.
 621                          */
 622                         goto start_new_line_no_skip;
 623                 }
 624                 /*
 625                  * Expand the value and push the Source on the stack of
 626                  * things being read.
 627                  */
 628                 source_p++;
 629                 UNCACHE_SOURCE();
 630                 {
 631                         Source t = (Source) alloca((int) sizeof (Source_rec));
 632                         source = push_macro_value(t,
 633                                                   buffer,
 634                                                   sizeof buffer,
 635                                                   source);
 636                 }
 637                 CACHE_SOURCE(1);
 638                 break;
 639         default:
 640                 /* We found the first proper char on the new line */
 641                 goto start_new_line_no_skip;
 642         }
 643 
 644         /*
 645          * We found the first normal char (one that starts an identifier)
 646          * on the newline.
 647          */
 648 start_new_line_no_skip:
 649         /* Inspect that first char to see if it maybe is special anyway */
 650         switch (GET_CHAR()) {
 651         case nul_char:
 652                 GET_NEXT_BLOCK(source);
 653                 if (source == NULL) {
 654                         GOTO_STATE(on_eoln_state);
 655                 }
 656                 goto start_new_line_no_skip;
 657         case newline_char:
 658                 /* Just in case */
 659                 goto start_new_line;
 660         case exclam_char:
 661                 /* Evaluate the line before it is read */
 662                 string_start = source_p + 1;
 663                 macro_seen_in_string = false;
 664                 /* Stuff the line in a string so we can eval it. */
 665                 for (; 1; source_p++) {
 666                         switch (GET_CHAR()) {
 667                         case newline_char:
 668                                 goto eoln_1;
 669                         case nul_char:
 670                                 if (source->fd > 0) {
 671                                         if (!macro_seen_in_string) {
 672                                                 macro_seen_in_string = true;
 673                                                 INIT_STRING_FROM_STACK(
 674                                                       name_string, name_buffer);
 675                                         }
 676                                         append_string(string_start,
 677                                                       &name_string,
 678                                                       source_p - string_start);
 679                                         GET_NEXT_BLOCK(source);
 680                                         string_start = source_p;
 681                                         source_p--;
 682                                         break;
 683                                 }
 684                         eoln_1:
 685                                 if (!macro_seen_in_string) {
 686                                         INIT_STRING_FROM_STACK(name_string,
 687                                                                name_buffer);
 688                                 }
 689                                 append_string(string_start,
 690                                               &name_string,
 691                                               source_p - string_start);
 692                                 extrap = (Source)
 693                                   alloca((int) sizeof (Source_rec));
 694                                 extrap->string.buffer.start = NULL;
 695                                 extrap->inp_buf =
 696                                   extrap->inp_buf_ptr =
 697                                     extrap->inp_buf_end = NULL;
 698                                 extrap->error_converting = false;
 699                                 if (*source_p == (int) nul_char) {
 700                                         source_p++;
 701                                 }
 702                                 /* Eval the macro */
 703                                 expand_value(GETNAME(name_string.buffer.start,
 704                                                      FIND_LENGTH),
 705                                              &extrap->string,
 706                                              false);
 707                                 if (name_string.free_after_use) {
 708                                         retmem(name_string.buffer.start);
 709                                 }
 710                                 UNCACHE_SOURCE();
 711                                 extrap->string.text.p =
 712                                   extrap->string.buffer.start;
 713                                 extrap->fd = -1;
 714                                 /* And push the value */
 715                                 extrap->previous = source;
 716                                 source = extrap;
 717                                 CACHE_SOURCE(0);
 718                                 goto line_evald;
 719                         }
 720                 }
 721         default:
 722                 goto line_evald;
 723         }
 724 
 725         /* We now have a line we can start reading */
 726  line_evald:
 727         if (source == NULL) {
 728                 GOTO_STATE(exit_state);
 729         }
 730         /* Check if this is an include command */
 731         if ((makefile_type == reading_makefile) &&
 732             !source->already_expanded) {
 733             if (include_space[0] == (int) nul_char) {
 734                 MBSTOWCS(include_space, "include ");
 735                 MBSTOWCS(include_tab, "include\t");
 736             }
 737             if ((IS_WEQUALN(source_p, include_space, 8)) ||
 738                 (IS_WEQUALN(source_p, include_tab, 8))) {
 739                 source_p += 7;
 740                 if (iswspace(*source_p)) {
 741                         Makefile_type save_makefile_type;
 742                         wchar_t         *name_start;
 743                         int             name_length;
 744 
 745                         /*
 746                          * Yes, this is an include.
 747                          * Skip spaces to get to the filename.
 748                          */
 749                         while (iswspace(*source_p) ||
 750                                (*source_p == (int) nul_char)) {
 751                                 switch (GET_CHAR()) {
 752                                 case nul_char:
 753                                         GET_NEXT_BLOCK(source);
 754                                         if (source == NULL) {
 755                                                 GOTO_STATE(on_eoln_state);
 756                                         }
 757                                         break;
 758 
 759                                 default:
 760                                         source_p++;
 761                                         break;
 762                                 }
 763                         }
 764 
 765                         string_start = source_p;
 766                         /* Find the end of the filename */
 767                         macro_seen_in_string = false;
 768                         while (!iswspace(*source_p) ||
 769                                (*source_p == (int) nul_char)) {
 770                                 switch (GET_CHAR()) {
 771                                 case nul_char:
 772                                         if (!macro_seen_in_string) {
 773                                                 INIT_STRING_FROM_STACK(name_string,
 774                                                                        name_buffer);
 775                                         }
 776                                         append_string(string_start,
 777                                                       &name_string,
 778                                                       source_p - string_start);
 779                                         macro_seen_in_string = true;
 780                                         GET_NEXT_BLOCK(source);
 781                                         string_start = source_p;
 782                                         if (source == NULL) {
 783                                                 GOTO_STATE(on_eoln_state);
 784                                         }
 785                                         break;
 786 
 787                                 default:
 788                                         source_p++;
 789                                         break;
 790                                 }
 791                         }
 792 
 793                         source->string.text.p = source_p;
 794                         if (macro_seen_in_string) {
 795                                 append_string(string_start,
 796                                               &name_string,
 797                                               source_p - string_start);
 798                                 name_start = name_string.buffer.start;
 799                                 name_length = name_string.text.p - name_start;
 800                         } else {
 801                                 name_start = string_start;
 802                                 name_length = source_p - string_start;
 803                         }
 804 
 805                         /* Strip "./" from the head of the name */
 806                         if ((name_start[0] == (int) period_char) &&
 807                            (name_start[1] == (int) slash_char)) {
 808                                 name_start += 2;
 809                                 name_length -= 2;
 810                         }
 811                         /* if include file name is surrounded by double quotes */
 812                         if ((name_start[0] == (int) doublequote_char) &&
 813                             (name_start[name_length - 1] == (int) doublequote_char)) {
 814                                 name_start += 1;
 815                                 name_length -= 2;
 816 
 817                                 /* if name does not begin with a slash char */
 818                                 if (name_start[0] != (int) slash_char) {
 819                                         if ((name_start[0] == (int) period_char) &&
 820                                             (name_start[1] == (int) slash_char)) {
 821                                                 name_start += 2;
 822                                                 name_length -= 2;
 823                                         }
 824 
 825                                         INIT_STRING_FROM_STACK(include_name, include_buffer);
 826                                         APPEND_NAME(true_makefile_name,
 827                                                       &include_name,
 828                                                       true_makefile_name->hash.length);
 829 
 830                                         wchar_t *slash = wsrchr(include_name.buffer.start, (int) slash_char);
 831                                         if (slash != NULL) {
 832                                                 include_name.text.p = slash + 1;
 833                                                 append_string(name_start,
 834                                                               &include_name,
 835                                                               name_length);
 836 
 837                                                 name_start = include_name.buffer.start;
 838                                                 name_length = include_name.text.p - name_start; 
 839                                         }
 840                                 }
 841                         }
 842 
 843                         /* Even when we run -n we want to create makefiles */
 844                         do_not_exec_rule = false;
 845                         makefile_name = GETNAME(name_start, name_length);
 846                         if (makefile_name->dollar) {
 847                                 String_rec      destination;
 848                                 wchar_t         buffer[STRING_BUFFER_LENGTH];
 849                                 wchar_t         *p;
 850                                 wchar_t         *q;
 851 
 852                                 INIT_STRING_FROM_STACK(destination, buffer);
 853                                 expand_value(makefile_name,
 854                                              &destination,
 855                                              false);
 856                                 for (p = destination.buffer.start;
 857                                      (*p != (int) nul_char) && iswspace(*p);
 858                                      p++);
 859                                 for (q = p;
 860                                      (*q != (int) nul_char) && !iswspace(*q);
 861                                      q++);
 862                                 makefile_name = GETNAME(p, q-p);
 863                                 if (destination.free_after_use) {
 864                                         retmem(destination.buffer.start);
 865                                 }
 866                         }
 867                         source_p++;
 868                         UNCACHE_SOURCE();
 869                         /* Read the file */
 870                         save_makefile_type = makefile_type;
 871                         if (read_simple_file(makefile_name,
 872                                              true,
 873                                              true,
 874                                              true,
 875                                              false,
 876                                              true,
 877                                              false) == failed) {
 878                                 fatal_reader(gettext("Read of include file `%s' failed"),
 879                                              makefile_name->string_mb);
 880                         }
 881                         makefile_type = save_makefile_type;
 882                         do_not_exec_rule = save_do_not_exec_rule;
 883                         CACHE_SOURCE(0);
 884                         goto start_new_line;
 885                 } else {
 886                         source_p -= 7;
 887                 }
 888             } else {
 889                 /* Check if the word include was split across 8K boundary. */
 890                 
 891                 tmp_bytes_left_in_string = source->string.text.end - source_p;
 892                 if (tmp_bytes_left_in_string < 8) {
 893                         tmp_maybe_include = false;
 894                         if (IS_WEQUALN(source_p,
 895                                        include_space,
 896                                        tmp_bytes_left_in_string)) {
 897                                 tmp_maybe_include = true;
 898                         }
 899                         if (tmp_maybe_include) {
 900                                 GET_NEXT_BLOCK(source);
 901                                 tmp_maybe_include = false;
 902                                 goto line_evald;
 903                         }
 904                 }
 905             }
 906         }
 907 
 908         /* Reset the status in preparation for the new line */
 909         for (nvp = &target; nvp != NULL; nvp = nvp->next) {
 910                 nvp->used = 0;
 911         }
 912         for (nvp = &depes; nvp != NULL; nvp = nvp->next) {
 913                 nvp->used = 0;
 914         }
 915         target_group_seen = false;
 916         command = command_tail = NULL;
 917         macro_value = NULL;
 918         append = false;
 919         current_names = &target;
 920         SET_STATE(scan_name_state);
 921         on_eoln_state = illegal_eoln_state;
 922         separator = none_seen;
 923 
 924         /* The state machine starts here */
 925  enter_state:
 926         while (1) switch (state) {
 927 
 928 /****************************************************************
 929  *      Scan name state
 930  */
 931 case scan_name_state:
 932         /* Scan an identifier. We skip over chars until we find a break char */
 933         /* First skip white space. */
 934         for (; 1; source_p++) switch (GET_CHAR()) {
 935         case nul_char:
 936                 GET_NEXT_BLOCK(source);
 937                 source_p--;
 938                 if (source == NULL) {
 939                         GOTO_STATE(on_eoln_state);
 940                 }
 941                 break;
 942         case newline_char:
 943                 /* We found the end of the line. */
 944                 /* Do postprocessing or return error */
 945                 source_p++;
 946                 if (source->fd >= 0) {
 947                         line_number++;
 948                 }
 949                 GOTO_STATE(on_eoln_state);
 950         case backslash_char:
 951                 /* Continuation */
 952                 if (*++source_p == (int) nul_char) {
 953                         GET_NEXT_BLOCK(source);
 954                         if (source == NULL) {
 955                                 GOTO_STATE(on_eoln_state);
 956                         }
 957                 }
 958                 if (*source_p == (int) newline_char) {
 959                         if (source->fd >= 0) {
 960                                 line_number++;
 961                         }
 962                 } else {
 963                         source_p--;
 964                 }
 965                 break;
 966         case tab_char:
 967         case space_char:
 968                 /* Whitespace is skipped */
 969                 break;
 970         case numbersign_char:
 971                 /* Comment. Skip over it */
 972                 for (; 1; source_p++) {
 973                         switch (GET_CHAR()) {
 974                         case nul_char:
 975                                 GET_NEXT_BLOCK_NOCHK(source);
 976                                 if (source == NULL) {
 977                                         GOTO_STATE(on_eoln_state);
 978                                 }
 979                                 if (source->error_converting) {
 980                                 // Illegal byte sequence - skip its first byte
 981                                         source->inp_buf_ptr++;
 982                                 }
 983                                 source_p--;
 984                                 break;
 985                         case backslash_char:
 986                                 if (*++source_p == (int) nul_char) {
 987                                         GET_NEXT_BLOCK_NOCHK(source);
 988                                         if (source == NULL) {
 989                                                 GOTO_STATE(on_eoln_state);
 990                                         }
 991                                         if (source->error_converting) {
 992                                         // Illegal byte sequence - skip its first byte
 993                                                 source->inp_buf_ptr++;
 994                                                 source_p--;
 995                                                 break;
 996                                         }
 997                                 }
 998                                 if(*source_p == (int) newline_char) {
 999                                         if (source->fd >= 0) {
1000                                                 line_number++;
1001                                         }
1002                                 }
1003                                 break;
1004                         case newline_char:
1005                                 source_p++;
1006                                 if (source->fd >= 0) {
1007                                         line_number++;
1008                                 }
1009                                 GOTO_STATE(on_eoln_state);
1010                         }
1011                 }
1012         case dollar_char:
1013                 /* Macro reference. Expand and push value */
1014                 if (source->already_expanded) {
1015                         goto scan_name;
1016                 }
1017                 source_p++;
1018                 UNCACHE_SOURCE();
1019                 {
1020                         Source t = (Source) alloca((int) sizeof (Source_rec));
1021                         source = push_macro_value(t,
1022                                                   buffer,
1023                                                   sizeof buffer,
1024                                                   source);
1025                 }
1026                 CACHE_SOURCE(1);
1027                 break;
1028         default:
1029                 /* End of white space */
1030                 goto scan_name;
1031         }
1032 
1033         /* First proper identifier character */
1034  scan_name:
1035 
1036         string_start = source_p;
1037         paren_count = brace_count = 0;
1038         macro_seen_in_string = false;
1039         resume_name_scan:
1040         for (; 1; source_p++) {
1041                 switch (GET_CHAR()) {
1042                 case nul_char:
1043                         /* Save what we have seen so far of the identifier */
1044                         if (source_p != string_start) {
1045                                 if (!macro_seen_in_string) {
1046                                         INIT_STRING_FROM_STACK(name_string,
1047                                                                name_buffer);
1048                                 }
1049                                 append_string(string_start,
1050                                               &name_string,
1051                                               source_p - string_start);
1052                                 macro_seen_in_string = true;
1053                         }
1054                         /* Get more text to read */
1055                         GET_NEXT_BLOCK(source);
1056                         string_start = source_p;
1057                         source_p--;
1058                         if (source == NULL) {
1059                                 GOTO_STATE(on_eoln_state);
1060                         }
1061                         break;
1062                 case newline_char:
1063                         if (paren_count > 0) {
1064                                 fatal_reader(gettext("Unmatched `(' on line"));
1065                         }
1066                         if (brace_count > 0) {
1067                                 fatal_reader(gettext("Unmatched `{' on line"));
1068                         }
1069                         source_p++;
1070                         /* Enter name */
1071                         current_names = enter_name(&name_string,
1072                                                    macro_seen_in_string,
1073                                                    string_start,
1074                                                    source_p - 1,
1075                                                    current_names,
1076                                                    &extra_names,
1077                                                    &target_group_seen);
1078                         first_target = false;
1079                         if (extra_names == NULL) {
1080                                 extra_names = (Name_vector)
1081                                   alloca((int) sizeof (Name_vector_rec));
1082                         }
1083                         /* Do postprocessing or return error */
1084                         if (source->fd >= 0) {
1085                                 line_number++;
1086                         }
1087                         GOTO_STATE(on_eoln_state);
1088                 case backslash_char:
1089                         /* Check if this is a quoting backslash */
1090                         if (!macro_seen_in_string) {
1091                                 INIT_STRING_FROM_STACK(name_string,
1092                                                        name_buffer);
1093                                 macro_seen_in_string = true;
1094                         }
1095                         append_string(string_start,
1096                                       &name_string,
1097                                       source_p - string_start);
1098                         if (*++source_p == (int) nul_char) {
1099                                 GET_NEXT_BLOCK(source);
1100                                 if (source == NULL) {
1101                                         GOTO_STATE(on_eoln_state);
1102                                 }
1103                         }
1104                         if (*source_p == (int) newline_char) {
1105                                 if (source->fd >= 0) {
1106                                         line_number++;
1107                                 }
1108                                 *source_p = (int) space_char;
1109                                 string_start = source_p;
1110                                 goto resume_name_scan;
1111                         } else {
1112                                 string_start = source_p;
1113                                 break;
1114                         }
1115                         break;
1116                 case numbersign_char:
1117                         if (paren_count + brace_count > 0) {
1118                                 break;
1119                         }
1120                         fatal_reader(gettext("Unexpected comment seen"));
1121                 case dollar_char:
1122                         if (source->already_expanded) {
1123                                 break;
1124                         }
1125                         /* Save the identifier so far */
1126                         if (source_p != string_start) {
1127                                 if (!macro_seen_in_string) {
1128                                         INIT_STRING_FROM_STACK(name_string,
1129                                                                name_buffer);
1130                                 }
1131                                 append_string(string_start,
1132                                               &name_string,
1133                                               source_p - string_start);
1134                                 macro_seen_in_string = true;
1135                         }
1136                         /* Eval and push the macro */
1137                         source_p++;
1138                         UNCACHE_SOURCE();
1139                         {
1140                                 Source t =
1141                                   (Source) alloca((int) sizeof (Source_rec));
1142                                 source = push_macro_value(t,
1143                                                           buffer,
1144                                                           sizeof buffer,
1145                                                           source);
1146                         }
1147                         CACHE_SOURCE(1);
1148                         string_start = source_p + 1;
1149                         break;
1150                 case parenleft_char:
1151                         paren_count++;
1152                         break;
1153                 case parenright_char:
1154                         if (--paren_count < 0) {
1155                                 fatal_reader(gettext("Unmatched `)' on line"));
1156                         }
1157                         break;
1158                 case braceleft_char:
1159                         brace_count++;
1160                         break;
1161                 case braceright_char:
1162                         if (--brace_count < 0) {
1163                                 fatal_reader(gettext("Unmatched `}' on line"));
1164                         }
1165                         break;
1166                 case ampersand_char:
1167                 case greater_char:
1168                 case bar_char:
1169                         if (paren_count + brace_count == 0) {
1170                                 source_p++;
1171                         }
1172                         /* Fall into */
1173                 case tab_char:
1174                 case space_char:
1175                         if (paren_count + brace_count > 0) {
1176                                 break;
1177                         }
1178                         current_names = enter_name(&name_string,
1179                                                    macro_seen_in_string,
1180                                                    string_start,
1181                                                    source_p,
1182                                                    current_names,
1183                                                    &extra_names,
1184                                                    &target_group_seen);
1185                         first_target = false;
1186                         if (extra_names == NULL) {
1187                                 extra_names = (Name_vector)
1188                                   alloca((int) sizeof (Name_vector_rec));
1189                         }
1190                         goto enter_state;
1191                 case colon_char:
1192                         if (paren_count + brace_count > 0) {
1193                                 break;
1194                         }
1195                         if (separator == conditional_seen) {
1196                                 break;
1197                         }
1198 /** POSIX **/
1199 #if 0
1200                         if(posix) {
1201                           emptycount = 0;
1202                         }
1203 #endif
1204 /** END POSIX **/
1205                         /* End of the target list. We now start reading */
1206                         /* dependencies or a conditional assignment */
1207                         if (separator != none_seen) {
1208                                 fatal_reader(gettext("Extra `:', `::', or `:=' on dependency line"));
1209                         }
1210                         /* Enter the last target */
1211                         if ((string_start != source_p) ||
1212                             macro_seen_in_string) {
1213                                 current_names =
1214                                   enter_name(&name_string,
1215                                              macro_seen_in_string,
1216                                              string_start,
1217                                              source_p,
1218                                              current_names,
1219                                              &extra_names,
1220                                              &target_group_seen);
1221                                 first_target = false;
1222                                 if (extra_names == NULL) {
1223                                         extra_names = (Name_vector)
1224                                           alloca((int)
1225                                                  sizeof (Name_vector_rec));
1226                                 }
1227                         }
1228                         /* Check if it is ":" "::" or ":=" */
1229                 scan_colon_label:
1230                         switch (*++source_p) {
1231                         case nul_char:
1232                                 GET_NEXT_BLOCK(source);
1233                                 source_p--;
1234                                 if (source == NULL) {
1235                                         GOTO_STATE(enter_dependencies_state);
1236                                 }
1237                                 goto scan_colon_label;
1238                         case equal_char:
1239                                 if(svr4) {
1240                                   fatal_reader(gettext("syntax error"));
1241                                 }
1242                                 separator = conditional_seen;
1243                                 source_p++;
1244                                 current_names = &depes;
1245                                 GOTO_STATE(scan_name_state);
1246                         case colon_char:
1247                                 separator = two_colon;
1248                                 source_p++;
1249                                 break;
1250                         default:
1251                                 separator = one_colon;
1252                         }
1253                         current_names = &depes;
1254                         on_eoln_state = enter_dependencies_state;
1255                         GOTO_STATE(scan_name_state);
1256                 case semicolon_char:
1257                         if (paren_count + brace_count > 0) {
1258                                 break;
1259                         }
1260                         /* End of reading names. Start reading the rule */
1261                         if ((separator != one_colon) &&
1262                             (separator != two_colon)) {
1263                                 fatal_reader(gettext("Unexpected command seen"));
1264                         }
1265                         /* Enter the last dependency */
1266                         if ((string_start != source_p) ||
1267                             macro_seen_in_string) {
1268                                 current_names =
1269                                   enter_name(&name_string,
1270                                              macro_seen_in_string,
1271                                              string_start,
1272                                              source_p,
1273                                              current_names,
1274                                              &extra_names,
1275                                              &target_group_seen);
1276                                 first_target = false;
1277                                 if (extra_names == NULL) {
1278                                         extra_names = (Name_vector)
1279                                           alloca((int)
1280                                                  sizeof (Name_vector_rec));
1281                                 }
1282                         }
1283                         source_p++;
1284                         /* Make sure to enter a rule even if the is */
1285                         /* no text here */
1286                         command = command_tail = ALLOC(Cmd_line);
1287                         command->next = NULL;
1288                         command->command_line = empty_name;
1289                         command->make_refd = false;
1290                         command->ignore_command_dependency = false;
1291                         command->assign = false;
1292                         command->ignore_error = false;
1293                         command->silent = false;
1294 
1295                         GOTO_STATE(scan_command_state);
1296                 case plus_char:
1297                         /*
1298                         ** following code drops the target separator plus char if it starts
1299                         ** a line.
1300                         */ 
1301                         if(first_target && !macro_seen_in_string &&
1302                                         source_p == string_start) {
1303                                 for (; 1; source_p++)
1304                                 switch (GET_CHAR()) {
1305                                 case nul_char:
1306                                         if (source_p != string_start) {
1307                                                 if (!macro_seen_in_string) {
1308                                                         INIT_STRING_FROM_STACK(name_string,
1309                                                                                name_buffer);
1310                                                 }
1311                                                 append_string(string_start,
1312                                                               &name_string,
1313                                                               source_p - string_start);
1314                                                 macro_seen_in_string = true;
1315                                         }
1316                                         GET_NEXT_BLOCK(source);
1317                                         string_start = source_p;
1318                                         source_p--;
1319                                         if (source == NULL) {
1320                                                 GOTO_STATE(on_eoln_state);
1321                                         }
1322                                         break;
1323                                 case plus_char:
1324                                         source_p++;
1325                                         while (*source_p == (int) nul_char) {
1326                                                 if (source_p != string_start) {
1327                                                         if (!macro_seen_in_string) {
1328                                                                 INIT_STRING_FROM_STACK(name_string,
1329                                                                                name_buffer);
1330                                                         }
1331                                                         append_string(string_start,
1332                                                                       &name_string,
1333                                                                       source_p - string_start);
1334                                                         macro_seen_in_string = true;
1335                                                 }
1336                                                 GET_NEXT_BLOCK(source);
1337                                                 string_start = source_p;
1338                                                 if (source == NULL) {
1339                                                         GOTO_STATE(on_eoln_state);
1340                                                 }
1341                                         }
1342                                         if (*source_p == (int) tab_char ||
1343                                                         *source_p == (int) space_char) {
1344                                                 macro_seen_in_string = false;
1345                                                 string_start = source_p + 1;
1346                                         } else {
1347                                                 goto resume_name_scan;
1348                                         }
1349                                         break;
1350                                 case tab_char:
1351                                 case space_char:
1352                                         string_start = source_p + 1;
1353                                         break;
1354                                 default:
1355                                         goto resume_name_scan;
1356                                 }
1357                         }
1358                         if (paren_count + brace_count > 0) {
1359                                 break;
1360                         }
1361                         /* We found "+=" construct */
1362                         if (source_p != string_start) {
1363                                 /* "+" is not a break char. */
1364                                 /* Ignore it if it is part of an identifier */
1365                                 source_p++;
1366                                 goto resume_name_scan;
1367                         }
1368                         /* Make sure the "+" is followed by a "=" */
1369                 scan_append:
1370                         switch (*++source_p) {
1371                         case nul_char:
1372                                 if (!macro_seen_in_string) {
1373                                         INIT_STRING_FROM_STACK(name_string,
1374                                                                name_buffer);
1375                                 }
1376                                 append_string(string_start,
1377                                               &name_string,
1378                                               source_p - string_start);
1379                                 GET_NEXT_BLOCK(source);
1380                                 source_p--;
1381                                 string_start = source_p;
1382                                 if (source == NULL) {
1383                                         GOTO_STATE(illegal_eoln_state);
1384                                 }
1385                                 goto scan_append;
1386                         case equal_char:
1387                                 if(!svr4) {
1388                                   append = true;
1389                                 } else {
1390                                   fatal_reader(gettext("Must be a separator on rules"));
1391                                 }
1392                                 break;
1393                         default:
1394                                 /* The "+" just starts a regular name. */
1395                                 /* Start reading that name */
1396                                 goto resume_name_scan;
1397                         }
1398                         /* Fall into */
1399                 case equal_char:
1400                         if (paren_count + brace_count > 0) {
1401                                 break;
1402                         }
1403                         /* We found macro assignment. */
1404                         /* Check if it is legal and if it is appending */
1405                         switch (separator) {
1406                         case none_seen:
1407                                 separator = equal_seen;
1408                                 on_eoln_state = enter_equal_state;
1409                                 break;
1410                         case conditional_seen:
1411                                 on_eoln_state = enter_conditional_state;
1412                                 break;
1413                         default:
1414                                 /* Reader must special check for "MACRO:sh=" */
1415                                 /* notation */
1416                                 if (sh_name == NULL) {
1417                                         MBSTOWCS(wcs_buffer, "sh");
1418                                         sh_name = GETNAME(wcs_buffer, FIND_LENGTH);
1419                                         MBSTOWCS(wcs_buffer, "shell");
1420                                         shell_name = GETNAME(wcs_buffer, FIND_LENGTH);
1421                                 }
1422 
1423                                 if (!macro_seen_in_string) {
1424                                         INIT_STRING_FROM_STACK(name_string,
1425                                                        name_buffer);
1426                                 }
1427                                 append_string(string_start,
1428                                               &name_string,
1429                                               source_p - string_start
1430                                 );
1431 
1432                                 if ( (((target.used == 1) &&
1433                                      (depes.used == 1) &&
1434                                      (depes.names[0] == sh_name)) ||
1435                                     ((target.used == 1) &&
1436                                      (depes.used == 0) &&
1437                                      (separator == one_colon) &&
1438                                      (GETNAME(name_string.buffer.start,FIND_LENGTH) == sh_name))) &&
1439                                     (!svr4)) {
1440                                         String_rec      macro_name;
1441                                         wchar_t         buffer[100];
1442 
1443                                         INIT_STRING_FROM_STACK(macro_name,
1444                                                                buffer);
1445                                         APPEND_NAME(target.names[0],
1446                                                       &macro_name,
1447                                                       FIND_LENGTH);
1448                                         append_char((int) colon_char,
1449                                                     &macro_name);
1450                                         APPEND_NAME(sh_name,
1451                                                       &macro_name,
1452                                                       FIND_LENGTH);
1453                                         target.names[0] =
1454                                           GETNAME(macro_name.buffer.start,
1455                                                   FIND_LENGTH);
1456                                         separator = equal_seen;
1457                                         on_eoln_state = enter_equal_state;
1458                                         break;
1459                                 } else if ( (((target.used == 1) &&
1460                                             (depes.used == 1) &&
1461                                             (depes.names[0] == shell_name)) ||
1462                                            ((target.used == 1) &&
1463                                             (depes.used == 0) &&
1464                                             (separator == one_colon) &&
1465                                             (GETNAME(name_string.buffer.start,FIND_LENGTH) == shell_name))) &&
1466                                            (!svr4)) {
1467                                         String_rec      macro_name;
1468                                         wchar_t         buffer[100];
1469 
1470                                         INIT_STRING_FROM_STACK(macro_name,
1471                                                                buffer);
1472                                         APPEND_NAME(target.names[0],
1473                                                       &macro_name,
1474                                                       FIND_LENGTH);
1475                                         append_char((int) colon_char,
1476                                                     &macro_name);
1477                                         APPEND_NAME(shell_name,
1478                                                       &macro_name,
1479                                                       FIND_LENGTH);
1480                                         target.names[0] =
1481                                           GETNAME(macro_name.buffer.start,
1482                                                   FIND_LENGTH);
1483                                         separator = equal_seen;
1484                                         on_eoln_state = enter_equal_state;
1485                                         break;
1486                                 } 
1487                                 if(svr4) {
1488                                   fatal_reader(gettext("syntax error"));
1489                                 }
1490                                 else {
1491                                   fatal_reader(gettext("Macro assignment on dependency line"));
1492                                 }
1493                         }
1494                         if (append) {
1495                                 source_p--;
1496                         }
1497                         /* Enter the macro name */
1498                         if ((string_start != source_p) ||
1499                             macro_seen_in_string) {
1500                                 current_names =
1501                                   enter_name(&name_string,
1502                                              macro_seen_in_string,
1503                                              string_start,
1504                                              source_p,
1505                                              current_names,
1506                                              &extra_names,
1507                                              &target_group_seen);
1508                                 first_target = false;
1509                                 if (extra_names == NULL) {
1510                                         extra_names = (Name_vector)
1511                                           alloca((int)
1512                                                  sizeof (Name_vector_rec));
1513                                 }
1514                         }
1515                         if (append) {
1516                                 source_p++;
1517                         }
1518                         macro_value = NULL;
1519                         source_p++;
1520                         distance = 0;
1521                         /* Skip whitespace to the start of the value */
1522                         macro_seen_in_string = false;
1523                         for (; 1; source_p++) {
1524                                 switch (GET_CHAR()) {
1525                                 case nul_char:
1526                                         GET_NEXT_BLOCK(source);
1527                                         source_p--;
1528                                         if (source == NULL) {
1529                                                 GOTO_STATE(on_eoln_state);
1530                                         }
1531                                         break;
1532                                 case backslash_char:
1533                                         if (*++source_p == (int) nul_char) {
1534                                                 GET_NEXT_BLOCK(source);
1535                                                 if (source == NULL) {
1536                                                         GOTO_STATE(on_eoln_state);
1537                                                 }
1538                                         }
1539                                         if (*source_p != (int) newline_char) {
1540                                                 if (!macro_seen_in_string) {
1541                                                         macro_seen_in_string =
1542                                                           true;
1543                                                         INIT_STRING_FROM_STACK(name_string,
1544                                                                                name_buffer);
1545                                                 }
1546                                                 append_char((int)
1547                                                             backslash_char,
1548                                                             &name_string);
1549                                                 append_char(*source_p,
1550                                                             &name_string);
1551                                                 string_start = source_p+1;
1552                                                 goto macro_value_start;
1553                                         } else {
1554                                             if (source->fd >= 0) {
1555                                                 line_number++;
1556                                             }
1557                                         }
1558                                         break;
1559                                 case newline_char:
1560                                 case numbersign_char:
1561                                         string_start = source_p;
1562                                         goto macro_value_end;
1563                                 case tab_char:
1564                                 case space_char:
1565                                         break;
1566                                 default:
1567                                         string_start = source_p;
1568                                         goto macro_value_start;
1569                                 }
1570                         }
1571                 macro_value_start:
1572                         /* Find the end of the value */
1573                         for (; 1; source_p++) {
1574                                 if (distance != 0) {
1575                                         *source_p = *(source_p + distance);
1576                                 }
1577                                 switch (GET_CHAR()) {
1578                                 case nul_char:
1579                                         if (!macro_seen_in_string) {
1580                                                 macro_seen_in_string = true;
1581                                                 INIT_STRING_FROM_STACK(name_string,
1582                                                                        name_buffer);
1583                                         }
1584                                         append_string(string_start,
1585                                                       &name_string,
1586                                                       source_p - string_start);
1587                                         GET_NEXT_BLOCK(source);
1588                                         string_start = source_p;
1589                                         source_p--;
1590                                         if (source == NULL) {
1591                                                 GOTO_STATE(on_eoln_state);
1592                                         }
1593                                         break;
1594                                 case backslash_char:
1595                                         source_p++;
1596                                         if (distance != 0) {
1597                                                 *source_p =
1598                                                   *(source_p + distance);
1599                                         }
1600                                         if (*source_p == (int) nul_char) {
1601                                                 if (!macro_seen_in_string) {
1602                                                         macro_seen_in_string =
1603                                                           true;
1604                                                         INIT_STRING_FROM_STACK(name_string,
1605                                                                                name_buffer);
1606                                                 }
1607 
1608 /*  BID_1225561 */
1609                                                 *(source_p - 1) = (int) space_char;
1610                                                 append_string(string_start,
1611                                                               &name_string,
1612                                                               source_p -
1613                                                               string_start - 1);
1614                                                 GET_NEXT_BLOCK(source);
1615                                                 string_start = source_p;
1616                                                 if (source == NULL) {
1617                                                         GOTO_STATE(on_eoln_state);
1618                                                 }
1619                                                 if (distance != 0) {
1620                                                         *source_p =
1621                                                           *(source_p +
1622                                                             distance);
1623                                                 }
1624                                                 if (*source_p == (int) newline_char) {
1625                                                         append_char((int) space_char, &name_string);
1626                                                 } else {
1627                                                         append_char((int) backslash_char, &name_string);
1628                                                 }
1629 /****************/
1630                                         }
1631                                         if (*source_p == (int) newline_char) {
1632                                                 source_p--;
1633                                                 line_number++;
1634                                                 distance++;
1635                                                 *source_p = (int) space_char;
1636                                                 while ((*(source_p +
1637                                                           distance + 1) ==
1638                                                         (int) tab_char) ||
1639                                                        (*(source_p +
1640                                                           distance + 1) ==
1641                                                         (int) space_char)) {
1642                                                         distance++;
1643                                                 }
1644                                         }
1645                                         break;
1646                                 case newline_char:
1647                                 case numbersign_char:
1648                                         goto macro_value_end;
1649                                 }
1650                         }
1651                 macro_value_end:
1652                         /* Complete the value in the string */
1653                         if (!macro_seen_in_string) {
1654                                 macro_seen_in_string = true;
1655                                 INIT_STRING_FROM_STACK(name_string,
1656                                                        name_buffer);
1657                         }
1658                         append_string(string_start,
1659                                       &name_string,
1660                                       source_p - string_start);
1661                         if (name_string.buffer.start != name_string.text.p) {
1662                                         macro_value =
1663                                           GETNAME(name_string.buffer.start,
1664                                                   FIND_LENGTH);
1665                                 }
1666                         if (name_string.free_after_use) {
1667                                 retmem(name_string.buffer.start);
1668                         }
1669                         for (; distance > 0; distance--) {
1670                                 *source_p++ = (int) space_char;
1671                         }
1672                         GOTO_STATE(on_eoln_state);
1673                 }
1674         }
1675 
1676 /****************************************************************
1677  *      enter dependencies state
1678  */
1679  case enter_dependencies_state:
1680  enter_dependencies_label:
1681 /* Expects pointer on first non whitespace char after last dependency. (On */
1682 /* next line.) We end up here after having read a "targets : dependencies" */
1683 /* line. The state checks if there is a rule to read and if so dispatches */
1684 /* to scan_command_state scan_command_state reads one rule line and the */
1685 /* returns here */
1686 
1687         /* First check if the first char on the next line is special */
1688         switch (GET_CHAR()) {
1689         case nul_char:
1690                 GET_NEXT_BLOCK(source);
1691                 if (source == NULL) {
1692                         break;
1693                 }
1694                 goto enter_dependencies_label;
1695         case exclam_char:
1696                 /* The line should be evaluate before it is read */
1697                 macro_seen_in_string = false;
1698                 string_start = source_p + 1;
1699                 for (; 1; source_p++) {
1700                         switch (GET_CHAR()) {
1701                         case newline_char:
1702                                 goto eoln_2;
1703                         case nul_char:
1704                                 if (source->fd > 0) {
1705                                         if (!macro_seen_in_string) {
1706                                                 macro_seen_in_string = true;
1707                                                 INIT_STRING_FROM_STACK(name_string,
1708                                                                        name_buffer);
1709                                         }
1710                                         append_string(string_start,
1711                                                       &name_string,
1712                                                       source_p - string_start);
1713                                         GET_NEXT_BLOCK(source);
1714                                         string_start = source_p;
1715                                         source_p--;
1716                                         break;
1717                                 }
1718                         eoln_2:
1719                                 if (!macro_seen_in_string) {
1720                                         INIT_STRING_FROM_STACK(name_string,
1721                                                                name_buffer);
1722                                 }
1723                                 append_string(string_start,
1724                                               &name_string,
1725                                               source_p - string_start);
1726                                 extrap = (Source)
1727                                   alloca((int) sizeof (Source_rec));
1728                                 extrap->string.buffer.start = NULL;
1729                                 extrap->inp_buf =
1730                                   extrap->inp_buf_ptr =
1731                                     extrap->inp_buf_end = NULL;
1732                                 extrap->error_converting = false;
1733                                 expand_value(GETNAME(name_string.buffer.start,
1734                                                      FIND_LENGTH),
1735                                              &extrap->string,
1736                                              false);
1737                                 if (name_string.free_after_use) {
1738                                         retmem(name_string.buffer.start);
1739                                 }
1740                                 UNCACHE_SOURCE();
1741                                 extrap->string.text.p =
1742                                   extrap->string.buffer.start;
1743                                 extrap->fd = -1;
1744                                 extrap->previous = source;
1745                                 source = extrap;
1746                                 CACHE_SOURCE(0);
1747                                 goto enter_dependencies_label;
1748                         }
1749                 }
1750         case dollar_char:
1751                 if (source->already_expanded) {
1752                         break;
1753                 }
1754                 source_p++;
1755                 UNCACHE_SOURCE();
1756                 {
1757                         Source t = (Source) alloca((int) sizeof (Source_rec));
1758                         source = push_macro_value(t,
1759                                                   buffer,
1760                                                   sizeof buffer,
1761                                                   source);
1762                 }
1763                 CACHE_SOURCE(0);
1764                 goto enter_dependencies_label;
1765         case numbersign_char:
1766                 if (makefile_type != reading_makefile) {
1767                         source_p++;
1768                         GOTO_STATE(scan_command_state);
1769                 }
1770                 for (; 1; source_p++) {
1771                         switch (GET_CHAR()) {
1772                         case nul_char:
1773                                 GET_NEXT_BLOCK_NOCHK(source);
1774                                 if (source == NULL) {
1775                                         GOTO_STATE(on_eoln_state);
1776                                 }
1777                                 if (source->error_converting) {
1778                                 // Illegal byte sequence - skip its first byte
1779                                         source->inp_buf_ptr++;
1780                                 }
1781                                 source_p--;
1782                                 break;
1783                         case backslash_char:
1784                                 if (*++source_p == (int) nul_char) {
1785                                         GET_NEXT_BLOCK_NOCHK(source);
1786                                         if (source == NULL) {
1787                                                 GOTO_STATE(on_eoln_state);
1788                                         }
1789                                         if (source->error_converting) {
1790                                         // Illegal byte sequence - skip its first byte
1791                                                 source->inp_buf_ptr++;
1792                                                 source_p--;
1793                                                 break;
1794                                         }
1795                                 }
1796                                 if(*source_p == (int) newline_char) {
1797                                         if (source->fd >= 0) {
1798                                                 line_number++;
1799                                         }
1800                                 }
1801                                 break;
1802                         case newline_char:
1803                                 source_p++;
1804                                 if (source->fd >= 0) {
1805                                         line_number++;
1806                                 }
1807                                 goto enter_dependencies_label;
1808                         }
1809                 }
1810 
1811         case tab_char:
1812                 GOTO_STATE(scan_command_state);
1813         }
1814 
1815         /* We read all the command lines for the target/dependency line. */
1816         /* Enter the stuff */
1817         enter_target_groups_and_dependencies( &target, &depes, command, 
1818                                              separator, target_group_seen);
1819 
1820         goto start_new_line;
1821 
1822 /****************************************************************
1823  *      scan command state
1824  */
1825 case scan_command_state:
1826         /* We need to read one rule line. Do that and return to */
1827         /* the enter dependencies state */
1828         string_start = source_p;
1829         macro_seen_in_string = false;
1830         for (; 1; source_p++) {
1831                 switch (GET_CHAR()) {
1832                 case backslash_char:
1833                         if (!macro_seen_in_string) {
1834                                 INIT_STRING_FROM_STACK(name_string,
1835                                                        name_buffer);
1836                         }
1837                         append_string(string_start,
1838                                       &name_string,
1839                                       source_p - string_start);
1840                         macro_seen_in_string = true;
1841                         if (*++source_p == (int) nul_char) {
1842                                 GET_NEXT_BLOCK(source);
1843                                 if (source == NULL) {
1844                                         string_start = source_p;
1845                                         goto command_newline;
1846                                 }
1847                         }
1848                         append_char((int) backslash_char, &name_string);
1849                         append_char(*source_p, &name_string);
1850                         if (*source_p == (int) newline_char) {
1851                                 if (source->fd >= 0) {
1852                                         line_number++;
1853                                 }
1854                                 if (*++source_p == (int) nul_char) {
1855                                         GET_NEXT_BLOCK(source);
1856                                         if (source == NULL) {
1857                                                 string_start = source_p;
1858                                                 goto command_newline;
1859                                         }
1860                                 }
1861                                 if (*source_p == (int) tab_char) {
1862                                         source_p++;
1863                                 }
1864                         } else {
1865                                 if (*++source_p == (int) nul_char) {
1866                                         GET_NEXT_BLOCK(source);
1867                                         if (source == NULL) {
1868                                                 string_start = source_p;
1869                                                 goto command_newline;
1870                                         }
1871                                 }
1872                         }
1873                         string_start = source_p;
1874                         if ((*source_p == (int) newline_char) ||
1875                             (*source_p == (int) backslash_char) ||
1876                             (*source_p == (int) nul_char)) {
1877                                 source_p--;
1878                         }
1879                         break;
1880                 case newline_char:
1881                 command_newline:
1882                         if ((string_start != source_p) ||
1883                             macro_seen_in_string) {
1884                                 if (macro_seen_in_string) {
1885                                         append_string(string_start,
1886                                                       &name_string,
1887                                                       source_p - string_start);
1888                                         string_start =
1889                                           name_string.buffer.start;
1890                                         string_end = name_string.text.p;
1891                                 } else {
1892                                         string_end = source_p;
1893                                 }
1894                                 while ((*string_start != (int) newline_char) &&
1895                                        iswspace(*string_start)){
1896                                         string_start++;
1897                                 }
1898                                 if ((string_end > string_start) ||
1899                                     (makefile_type == reading_statefile)) {
1900                                         if (command_tail == NULL) {
1901                                                 command =
1902                                                   command_tail =
1903                                                     ALLOC(Cmd_line);
1904                                         } else {
1905                                                 command_tail->next =
1906                                                   ALLOC(Cmd_line);
1907                                                 command_tail =
1908                                                   command_tail->next;
1909                                         }
1910                                         command_tail->next = NULL;
1911                                         command_tail->make_refd = false;
1912                                         command_tail->ignore_command_dependency = false;
1913                                         command_tail->assign = false;
1914                                         command_tail->ignore_error = false;
1915                                         command_tail->silent = false;
1916                                         command_tail->command_line =
1917                                           GETNAME(string_start,
1918                                                   string_end - string_start);
1919                                         if (macro_seen_in_string &&
1920                                             name_string.free_after_use) {
1921                                                 retmem(name_string.
1922                                                        buffer.start);
1923                                         }
1924                                 }
1925                         }
1926                         do {
1927                                 if ((source != NULL) && (source->fd >= 0)) {
1928                                         line_number++;
1929                                 }
1930                                 if ((source != NULL) &&
1931                                     (*++source_p == (int) nul_char)) {
1932                                         GET_NEXT_BLOCK(source);
1933                                         if (source == NULL) {
1934                                                 GOTO_STATE(on_eoln_state);
1935                                         }
1936                                 }
1937                         } while (*source_p == (int) newline_char);
1938 
1939                         GOTO_STATE(enter_dependencies_state);
1940                 case nul_char:
1941                         if (!macro_seen_in_string) {
1942                                 INIT_STRING_FROM_STACK(name_string,
1943                                                        name_buffer);
1944                         }
1945                         append_string(string_start,
1946                                       &name_string,
1947                                       source_p - string_start);
1948                         macro_seen_in_string = true;
1949                         GET_NEXT_BLOCK(source);
1950                         string_start = source_p;
1951                         source_p--;
1952                         if (source == NULL) {
1953                                 GOTO_STATE(enter_dependencies_state);
1954                         }
1955                         break;
1956                 }
1957         }
1958 
1959 /****************************************************************
1960  *      enter equal state
1961  */
1962 case enter_equal_state:
1963         if (target.used != 1) {
1964                 GOTO_STATE(poorly_formed_macro_state);
1965         }
1966         enter_equal(target.names[0], macro_value, append);
1967         goto start_new_line;
1968 
1969 /****************************************************************
1970  *      enter conditional state
1971  */
1972 case enter_conditional_state:
1973         if (depes.used != 1) {
1974                 GOTO_STATE(poorly_formed_macro_state);
1975         }
1976         for (nvp = &target; nvp != NULL; nvp = nvp->next) {
1977                 for (i = 0; i < nvp->used; i++) {
1978                         enter_conditional(nvp->names[i],
1979                                           depes.names[0],
1980                                           macro_value,
1981                                           append);
1982                 }
1983         }
1984         goto start_new_line;
1985 
1986 /****************************************************************
1987  *      Error states
1988  */
1989 case illegal_bytes_state:
1990         fatal_reader(gettext("Invalid byte sequence"));
1991 case illegal_eoln_state:
1992         if (line_number > 1) {
1993                 if (line_started_with_space == (line_number - 1)) {
1994                         line_number--;
1995                         fatal_reader(gettext("Unexpected end of line seen\n\t*** missing separator (did you mean TAB instead of 8 spaces?)"));
1996                 }
1997         }
1998         fatal_reader(gettext("Unexpected end of line seen"));
1999 case poorly_formed_macro_state:
2000         fatal_reader(gettext("Badly formed macro assignment"));
2001 case exit_state:
2002         return;
2003 default:
2004         fatal_reader(gettext("Internal error. Unknown reader state"));
2005 }
2006 }
2007 
2008 /*
2009  *      push_macro_value(bp, buffer, size, source)
2010  *
2011  *      Macro and function that evaluates one macro
2012  *      and makes the reader read from the value of it
2013  *
2014  *      Return value:
2015  *                              The source block to read the macro from
2016  *
2017  *      Parameters:
2018  *              bp              The new source block to fill in
2019  *              buffer          Buffer to read from
2020  *              size            size of the buffer
2021  *              source          The old source block
2022  *
2023  *      Global variables used:
2024  */
2025 static Source
2026 push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source)
2027 {
2028         bp->string.buffer.start = bp->string.text.p = buffer;
2029         bp->string.text.end = NULL;
2030         bp->string.buffer.end = buffer + (size/SIZEOFWCHAR_T);
2031         bp->string.free_after_use = false;
2032         bp->inp_buf =
2033           bp->inp_buf_ptr =
2034             bp->inp_buf_end = NULL;
2035         bp->error_converting = false;
2036         expand_macro(source, &bp->string, (wchar_t *) NULL, false);
2037         bp->string.text.p = bp->string.buffer.start;
2038 
2039         /* 4209588: 'make' doesn't understand a macro with whitespaces in the head as target.
2040          * strip whitespace from the begining of the macro value
2041          */
2042         while (iswspace(*bp->string.text.p)) {
2043                 bp->string.text.p++;
2044         }
2045 
2046         bp->fd = -1;
2047         bp->already_expanded = true;
2048         bp->previous = source;
2049         return bp;
2050 }
2051 
2052 /*
2053  *      enter_target_groups_and_dependencies(target, depes, command, separator,
2054  *                                           target_group_seen)
2055  *
2056  *      Parameters:
2057  *              target          Structure that shows the target(s) on the line
2058  *                              we are currently parsing. This can looks like
2059  *                              target1 .. targetN : dependencies
2060  *                                                      commands
2061  *                              or
2062  *                              target1 + .. + targetN : dependencies
2063  *                                                       commands
2064  *              depes           Dependencies
2065  *              command         Points to the command(s) to be executed for 
2066  *                              this target.
2067  *              separator       : or :: or :=
2068  *              target_group_seen       Set if we have target1 + .. + targetN
2069  *              
2070  *              
2071  *      After reading the command lines for a target, this routine 
2072  *      is called to setup the dependencies and the commands for it.
2073  *      If the target is a % pattern or part of a target group, then 
2074  *      the appropriate routines are called.
2075  */
2076         
2077 void
2078 enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen)
2079 {
2080         int                     i;
2081         Boolean                 reset= true;
2082         Chain                   target_group_member;
2083         Percent                 percent_ptr;
2084 
2085         for (; target != NULL; target = target->next) {
2086                 for (i = 0; i < target->used; i++) {
2087                         if (target->names[i] != NULL) {
2088                                 if (target_group_seen) {
2089                                         target_group_member =
2090                                           find_target_groups(target, i, reset);
2091                                         if(target_group_member == NULL) {
2092                                                 fatal_reader(gettext("Unexpected '+' on dependency line"));
2093                                         }
2094                                 }
2095                                 reset = false;
2096 
2097                                 /* If we saw it in the makefile it must be
2098                                  * a file */
2099                                 target->names[i]->stat.is_file = true;
2100                                 /* Make sure that we use dependencies 
2101                                  * entered for makefiles */
2102                                 target->names[i]->state = build_dont_know;
2103 
2104                                 /* If the target is special we delegate 
2105                                  * the processing */
2106                                 if (target->names[i]->special_reader 
2107                                     != no_special) {
2108                                         special_reader(target->names[i], 
2109                                                        depes, 
2110                                                        command);
2111                                 }       
2112                                 /* Check if this is a "a%b : x%y" type rule */
2113                                 else if (target->names[i]->percent) {
2114                                         percent_ptr = 
2115                                           enter_percent(target->names[i], 
2116                                                         target->target_group[i], 
2117                                                         depes, command);
2118                                         if (target_group_seen) {
2119                                                 target_group_member->percent_member =
2120                                                   percent_ptr;
2121                                         }
2122                                 } else if (target->names[i]->dollar) {
2123                                         enter_dyntarget(target->names[i]);
2124                                         enter_dependencies
2125                                           (target->names[i],
2126                                            target->target_group[i],
2127                                            depes,       
2128                                            command,
2129                                            separator);
2130                                 } else {
2131                                         if (target_group_seen) {
2132                                                 target_group_member->percent_member =
2133                                                   NULL;
2134                                         }
2135                                 
2136                                         enter_dependencies
2137                                           (target->names[i],
2138                                            target->target_group[i],
2139                                            depes,       
2140                                            command,
2141                                            separator);
2142                                 }
2143                         }
2144                 }
2145         }
2146 }
2147                                      
2148