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