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