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