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