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