1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** FRONTEND.C 82** 83** FACILITY: 84** 85** Interface Definition Language (IDL) Compiler 86** 87** ABSTRACT: 88** 89** Mainline for IDL compilers. 90** 91** VERSION: DCE 1.0 92** 93*/ 94 95#include <signal.h> 96 97#ifdef vms 98# include <types.h> 99# include <stat.h> 100# include <stsdef.h> 101# include <descrip.h> 102#else 103# include <sys/types.h> 104# include <sys/stat.h> 105# include <fcntl.h> 106# include <stdio.h> 107#endif 108 109#include <frontend.h> 110#include <astp.h> 111#include <astp_dmp.h> 112#include <checker.h> 113#include <command.h> 114#include <errors.h> 115#include <files.h> 116#include <getflags.h> 117#include <propagat.h> 118#include <message.h> 119 120#define CONFIG_SUFFIX ".acf" 121 122/* 123 * Macro to "close" a pipe - don't actually call pclose since it can cause hangs 124 * in certain instances where a parent process opens and closes several pipes, 125 * apparently due to the underlying wait() call from pclose and the unpredict- 126 * ability of the order of child exits. 127 */ 128#include <errno.h> 129#define PCLOSE(stream) \ 130{ \ 131 char buf[256]; \ 132 /* Silently read to eof - extra lines should cause COMPABORT msg anyway */ \ 133 while (fgets(buf, sizeof(buf), stream) != NULL) ; \ 134} 135 136/* Globals */ 137 138/* Local data definitions. */ 139 140static boolean *saved_cmd_opt; /* Array of command option flags */ 141static void **saved_cmd_val; /* Array of command option values */ 142 143typedef struct FE_import_file_n_t { 144 struct FE_import_file_n_t * next; 145 STRTAB_str_t imported_fn_id; 146 STRTAB_str_t imported_full_fn_id; 147} FE_import_file_n_t; 148 149static FE_import_file_n_t * imported_file_list = NULL; 150 151extern boolean ASTP_parsing_main_idl; 152 153/* 154 * All the error reporting requires a parser location to access line 155 * numbers, etc. However, the APIs are structured such that they may 156 * invoke parser errors even when we are not in the middle of a parse. 157 * In that case, what's the correct line number? Who knows? Let's make 158 * a dummy location and hope we don't get any errors at the wrong time. 159 * -- jpeach 160 */ 161 162const parser_location_t empty_parser_location; 163 164/* 165** i n i t 166** 167** Frontend-specific initialization. 168*/ 169 170static void FE_init(void) 171{ 172 saved_cmd_opt = NULL; 173 saved_cmd_val = NULL; 174 175 KEYWORDS_init(); 176 NAMETABLE_init(); 177 AST_init(null_parser_location); 178} 179 180/* 181** c p p 182** 183** Sends the source file through CPP before giving it to lex. 184** The cpp_output argument is a file ID for the output from cpp. 185** UNIX only: cpp_output is connected to piped output from cpp. 186*/ 187 188#if defined(CPP) 189static void cpp 190( 191 char *cpp_cmd, /* [in] Base command to invoke cpp */ 192 char *cpp_opt, /* [in] Addtl command options for cpp */ 193 char *file_name, /* [in] Source full filespec; "" => stdin */ 194 char *dst_file_name ATTRIBUTE_UNUSED, /* [in] Target filespec (VMS) */ 195 char **def_strings, /* [in] List of #define's for preprocessor */ 196 char **undef_strings,/* [in] List of #undefine's for preprocessor */ 197 char **idir_list, /* [in] List of -I directories */ 198 FILE **cpp_output /*[out] File ID of cpp output */ 199) 200 201{ 202 char cmd[max_string_len]; /* Command to spawn cpp */ 203 204 cmd[0] = '\0'; 205 206 assert(cpp_cmd && *cpp_cmd); 207 208 /* Put together beginning of command. */ 209 210 strlcpy(cmd, cpp_cmd, sizeof(cmd)); 211 strlcat(cmd, " ", sizeof(cmd)); 212 strlcat(cmd, cpp_opt ? cpp_opt : "", sizeof(cmd)); 213 strlcat(cmd, " ", sizeof(cmd)); 214 strlcat(cmd, file_name ? file_name : "" , sizeof(cmd)); 215 216 /* Append the -D strings. */ 217 218 while (*def_strings) 219 { 220 strlcat(cmd, " -D", sizeof(cmd)); 221 strlcat(cmd, *def_strings++, sizeof(cmd)); 222 } 223 224 /* Append the -U strings. */ 225 while (*undef_strings) 226 { 227 strlcat(cmd, " -U", sizeof(cmd)); 228 strlcat(cmd, *undef_strings++, sizeof(cmd)); 229 } 230 231 /* If cpp_cmd is the default, append the -I directories. */ 232 233 if (strcmp(cpp_cmd, CMD_def_cpp_cmd) == 0) 234 { 235 while (*idir_list) 236 { 237 strlcat(cmd, " -I", sizeof(cmd)); 238 strlcat(cmd, *idir_list++, sizeof(cmd)); 239 } 240 } 241 242 /* Now execute the cpp command and open output file or pipe. */ 243 244 if (saved_cmd_opt[opt_verbose]) 245 message_print(NIDL_RUNCPP,cmd); 246 247#if 0 248 printf("CPP - %s\n", cmd); 249#endif 250 251 if ((*cpp_output = popen(cmd, "r")) == 0) 252 error(NIDL_INVOKECPP); 253} 254#endif 255 256/* 257** p a r s e _ a c f 258** 259** Invokes the ACF (Attribute Configuration File) parser on specified file. 260** 261** Note: If cmd_opt[opt_confirm], then no real work is done except to 262** issue messages for the verbose option. 263** 264** Returns: == 0 => success 265** != 0 => failure 266*/ 267 268static boolean parse_acf /* Returns true on success */ 269( 270 boolean *cmd_opt, /* [in] Array of command option flags */ 271 void **cmd_val, /* [in] Array of command option values */ 272 char *acf_file /* [in] ACF full file name */ 273) 274 275{ 276 FILE * acf_yyin = NULL; 277 char temp_path_name[max_string_len]; /* Full temp file pathname */ 278 void * acf_parser; 279 280 if (cmd_opt[opt_verbose]) 281 message_print(NIDL_PROCESSACF, acf_file); 282 if (cmd_opt[opt_confirm]) 283 return true; 284 285 /* 286 * lex & yacc intializations 287 */ 288 289 acf_parser = acf_parser_alloc(cmd_opt, cmd_val, acf_file); 290 291#if defined(CPP) 292 if (cmd_opt[opt_cpp]) 293 { 294 temp_path_name[0] = '\0'; 295 296 cpp((char *)cmd_val[opt_cpp], 297 (char *)cmd_val[opt_cpp_opt], 298 acf_file, 299 temp_path_name, 300 (char **)cmd_val[opt_cpp_def], 301 (char **)cmd_val[opt_cpp_undef], 302 (char **)cmd_val[opt_idir], 303 &acf_yyin); 304 } 305 else 306#endif 307 /* No cpp, just open source file */ 308 FILE_open(acf_file, &acf_yyin); 309 310 acf_parser_input(acf_parser, acf_yyin); 311 if (acf_yyparse(acf_parser) != 0 && acf_errcount(acf_parser) == 0) 312 { 313 log_error(acf_yylineno(acf_parser), NIDL_COMPABORT, NULL); 314 } 315 316#if defined(CPP) 317 if (cmd_opt[opt_cpp]) 318 PCLOSE(acf_yyin) 319 else 320#endif 321 fclose(acf_yyin); 322 323 if (acf_errcount(acf_parser) != 0) 324 { 325 acf_parser_destroy(acf_parser); 326 return false; 327 } 328 329 acf_parser_destroy(acf_parser); 330 return true; 331} 332 333/* 334** a l r e a d y _ i m p o r t e d 335** 336** Checks whether a file is already included in the parse or not. 337** 338** Returns TRUE if the import file has already been parsed. 339** Returns false otherwise (Including can't find the file.) 340** 341*/ 342 343static boolean already_imported 344( 345 STRTAB_str_t import_path_id /* The name to check */ 346) 347 348{ 349 char new_import_full_fn[max_string_len]; 350 STRTAB_str_t new_import_full_fn_id; 351 STRTAB_str_t new_import_fn_id; 352 char base_file_name[max_string_len]; 353 char base_file_ext[max_string_len]; 354 struct stat stat_buf; 355 FE_import_file_n_t * imported_file; 356 char const * * idir_list; 357 boolean alr_imp; 358 char const * file_name; 359 360 /* 361 * Get a string to lookup. 362 */ 363 STRTAB_str_to_string (import_path_id, &file_name); 364 idir_list = (char const * *)saved_cmd_val[opt_idir]; 365 366 /* 367 * Note that a lookup failure will not report a failure here; 368 * That will be reported when we actually try to import it. 369 */ 370 if (!FILE_lookup(file_name, idir_list, &stat_buf, new_import_full_fn, sizeof (new_import_full_fn))) 371 return false; 372 new_import_full_fn_id = STRTAB_add_string(new_import_full_fn); 373 374 /* 375 * Make sure there is no partial path information. 376 */ 377 if (!FILE_parse(new_import_full_fn, NULL, 0, base_file_name, sizeof(base_file_name), base_file_ext, sizeof(base_file_ext))) 378 return false; 379 380 strncat(base_file_name, base_file_ext, max_string_len); 381 new_import_fn_id = STRTAB_add_string(base_file_name); 382 383 /* 384 * Initialize the default return status. 385 */ 386 alr_imp = false; 387 388 imported_file = imported_file_list; 389 390 while ((imported_file != NULL) && (!alr_imp)) 391 { 392 if (new_import_fn_id == imported_file->imported_fn_id) 393 { 394 /* 395 * A match is found in the list. We are done. 396 */ 397 alr_imp = true; 398 } 399 imported_file = imported_file -> next; 400 } 401 402 /* 403 * Record the import we are about to do if not imported already. 404 */ 405 if (!alr_imp) 406 { 407 imported_file = NEW (FE_import_file_n_t); 408 imported_file -> imported_fn_id = new_import_fn_id; 409 imported_file -> imported_full_fn_id = new_import_full_fn_id; 410 imported_file -> next = imported_file_list; 411 imported_file_list = imported_file; 412 } 413 414 return alr_imp; 415} 416 417/* 418** p a r s e 419** 420** Invokes the parser on the specified IDL file. If the IDL file is 421** successfully parsed, and there is a related ACF file, then the ACF 422** file is parsed also. 423** 424** Returns: a pointer to the interface binding if the IDL file was parsed 425** successfully and the ACF file (if any) was parsed successfully; 426** NULL otherwise. 427*/ 428 429static boolean parse 430( 431 boolean *cmd_opt, /* [in] Array of command option flags */ 432 void **cmd_val, /* [in] Array of command option values */ 433 STRTAB_str_t idl_sid, /* [in] IDL filespec stringtable ID */ 434 /* STRTAB_NULL_STR => stdin */ 435 boolean idir_valid, /* [in] true => use import directory list */ 436 AST_interface_n_t **int_p /*[out] Ptr to interface node */ 437) 438{ 439 FILE *nidl_yyin = NULL; 440 441 char const *sf; /* Source filespec */ 442 char full_path_name[max_string_len]; /* Full source pathname */ 443 char temp_path_name[max_string_len]; /* Full temp file pathname */ 444 STRTAB_str_t full_pn_id; /* Full src path string id */ 445 char const * *idir_list; /* List of search directories */ 446 char file_dir[max_string_len]; /* Directory part of src file */ 447 boolean file_dir_is_cwd; /* T => file_dir current dir */ 448 char file_name[max_string_len]; /* File name part of src file */ 449 char acf_file[max_string_len]; /* ACF file name w/o dir */ 450 char full_acf_name[max_string_len]; /* Full ACF pathname */ 451 boolean acf_exists; /* T => ACF file exists */ 452 struct stat stat_buf; /* File lookup stats */ 453 int i=0; 454 455 void * nidl_parser; 456 457 /* One-time saving of command array addresses to static storage. */ 458 if (saved_cmd_opt == NULL) 459 saved_cmd_opt = cmd_opt; 460 if (saved_cmd_val == NULL) 461 saved_cmd_val = cmd_val; 462 463 /* 464 * If the idir_valid flag is set, look in the -I directories for the 465 * source file. Otherwise, just use the filespec as is. 466 */ 467 if (idir_valid) 468 idir_list = (char const * *)cmd_val[opt_idir]; 469 else 470 idir_list = NULL; 471 472 if (idl_sid == STRTAB_NULL_STR) /* stdin */ 473 full_path_name[0] = '\0'; 474 else 475 { 476 STRTAB_str_to_string(idl_sid, &sf); 477 if (!FILE_lookup(sf, idir_list, &stat_buf, full_path_name, sizeof (full_path_name))) 478 { 479 error(NIDL_FILENOTFND, sf); 480 return false; 481 } 482 } 483 484 if (cmd_opt[opt_verbose] && !ASTP_parsing_main_idl) 485 message_print(NIDL_IMPORTIDL, full_path_name); 486 487#if defined(CPP) 488 if (cmd_opt[opt_cpp]) 489 { 490 temp_path_name[0] = '\0'; 491 492 /* define the macro describing dceidl compiler (for conditional 493 constructions) */ 494 if (!add_def_string(DCEIDL_DEF)) 495 { 496 message_print(NIDL_INTERNAL_ERROR, "Warning: Couldn't define macro %s!\n", DCEIDL_DEF); 497 } 498 499 cpp((char *)cmd_val[opt_cpp], 500 (char *)cmd_val[opt_cpp_opt], 501 full_path_name, 502 temp_path_name, 503 (char **)cmd_val[opt_cpp_def], 504 (char **)cmd_val[opt_cpp_undef], 505 (char **)cmd_val[opt_idir], 506 &nidl_yyin); 507 } 508 else 509#endif 510 if (full_path_name[0] == '\0') /* stdin */ 511 nidl_yyin = stdin; 512 else 513 FILE_open(full_path_name, &nidl_yyin); 514 515 /* 516 * Setup file name for errors to the full file name 517 */ 518 set_name_for_errors((full_path_name[0] == '\0') ? "stdin" : full_path_name); 519 520 nidl_parser = nidl_parser_alloc(cmd_opt, cmd_val, full_path_name); 521 nidl_parser_input(nidl_parser, nidl_yyin); 522 523#if YYDEBUG && 0 524 { 525 extern int nidl_yydebug; 526 nidl_yydebug = 1; 527 } 528#endif 529 530 if (nidl_yyparse(nidl_parser) != 0 && error_count == 0) 531 log_error(nidl_yylineno(nidl_parser), NIDL_COMPABORT, NULL); 532 *int_p = the_interface; 533 534 nidl_parser_destroy(nidl_parser); 535 536#if defined(CPP) 537 if (cmd_opt[opt_cpp]) 538 PCLOSE(nidl_yyin) 539 else 540#endif 541 fclose(nidl_yyin); 542 543 if (error_count != 0) 544 return false; /* Error parsing IDL */ 545 546 /* Successful parse: save IDL filespec in interface node. */ 547 if (the_interface != NULL) 548 { 549 full_pn_id = STRTAB_add_string(full_path_name); 550 the_interface->fe_info->file = full_pn_id; 551 } 552 else 553 { 554 if (ASTP_parsing_main_idl) return false; /* Shouldn't happen */ 555 } 556 557 /* 558 * Now see if there is an associated Attribute Configuration File (ACF). 559 * The ACF name is constructed from the IDL file name. The ACF file can 560 * be in any of the -I directories. 561 */ 562 if (!FILE_parse(full_path_name, file_dir, sizeof(file_dir), file_name, sizeof(file_name), (char *)NULL, 0)) 563 return false; 564 565 if (!FILE_form_filespec(file_name, (char *)NULL, CONFIG_SUFFIX, 566 (char *)NULL, acf_file, sizeof(acf_file))) 567 return false; 568#ifdef UNIX 569 /* 570 * If the created ACF filespec matches the file_name portion of the IDL 571 * filespec, it implies that the IDL filespec contains multiple '.'s - in 572 * this special case, append the ACF suffix to the filespec. 573 */ 574 if (strcmp(file_name, acf_file) == 0) 575 strlcat(acf_file, CONFIG_SUFFIX, sizeof(acf_file)); 576#endif 577 578 /* 579 * If the directory part of the source filespec is not the current dir, 580 * tack it on at the end of the include directory list. Note: we assume 581 * that there is enough room for a temporary extra entry in the idir list. 582 */ 583 idir_list = (char const **)cmd_val[opt_idir]; 584 file_dir_is_cwd = FILE_is_cwd(file_dir); 585 586 if (!file_dir_is_cwd) 587 { 588 for (i = 0 ; idir_list[i] != NULL ; i++) 589 ; 590 idir_list[i] = file_dir; 591 idir_list[i+1] = NULL; 592 } 593 594 acf_exists = FILE_lookup(acf_file, idir_list, &stat_buf, full_acf_name, sizeof (full_acf_name)); 595 596 if (!file_dir_is_cwd) 597 idir_list[i] = NULL; 598 599 if (!acf_exists) 600 return true; /* No ACF; return success */ 601 602 /* Parse the ACF. */ 603 if (!parse_acf(cmd_opt, cmd_val, full_acf_name)) 604 return false; /* Error parsing ACF */ 605 606 return true; /* Both IDL and ACF parsed without errors */ 607} 608 609/* 610 * F E _ p a r s e _ i m p o r t 611 * 612 * Parse an import file. 613 * This involves pushing the state of the current parse, initing a few 614 * cells, calling parse, and restoring the state of the current parse. 615 * 616 * Parametric inputs: The string table id of the filename we wish to parse. 617 * Global inputs: All the parse and lex static storage that maintains parse 618 * state. 619 * Parametric outputs: None 620 * Global outputs: The parse state is restored to its value on entry. 621 * 622 * Routine value: None. 623 */ 624 625AST_interface_n_t *FE_parse_import 626( 627 STRTAB_str_t new_input /* [in] string table id of file to parse */ 628) 629{ 630 631 /* 632 * BISON/FLEX nester parser support 633 * 634 * FE_parse_import() is called by the import_file rule in 635 * nidl.y. We can be called recursively, for each file requested 636 * to be included. To support this with non-reentrant Flex 637 * and Bison parsers, we save the current Flex/Bison state, 638 * create a new, initialized state for the ACF & NIDL x Flex & BISON 639 * state machines, and parse the import. When we are done, 640 * we delete the temporary parsers states used to do the import, 641 * and restore the parser state variables back to where they were. 642 * 643 * The support logic to do context switching of parser state machines 644 * can be found at the end of nidl.l, nidl.y, acf.l, acf.y 645 * 646 * For any given import, we have to save and reset FOUR different 647 * state machines: 648 * 649 * ACF parser, ACF flexxer, NIDL parser, NIDL lexxer 650 * 651 */ 652 653 boolean saved_ASTP_parsing_main_idl; 654 char saved_current_file[ PATH_MAX ]; 655 AST_interface_n_t *int_p; 656 657 unsigned * saved_yylineno_p = yylineno_p; 658 FILE * saved_yyin_p = yyin_p; 659 660 /* Saved interface attributes */ 661 AST_interface_n_t *saved_interface; 662#if 0 663 int saved_op_count; 664#endif 665 666 /* 667 * Return now, if the file is already imported. 668 */ 669 if (already_imported (new_input)) 670 return (AST_interface_n_t *)NULL; 671 672 /* save the AST state */ 673 674 saved_ASTP_parsing_main_idl = ASTP_parsing_main_idl; 675 inq_name_for_errors(saved_current_file, sizeof (saved_current_file)); 676 677 /* 678 * Save interface information 679 */ 680 681 saved_interface = the_interface; 682#if 0 683 saved_op_count = the_interface ? the_interface->op_count : 0; 684#endif 685 686 /* 687 * Initialize interface attributes 688 */ 689 690 the_interface = NULL; 691 692 /* 693 * We have now saved away all the state of the current parse. 694 * Initialize a few cells, open the imported file and recursively invoke the 695 * parse. 696 */ 697 698 if (saved_interface) 699 ASTP_parsing_main_idl = false; 700 701 /* 702 * Create new, empty and initialized parser context to 703 * do the import. 704 */ 705 706 /* Now we can parse the import file.... 707 * Parse the file. Routine parse normally returns a AST_interface_n_t, 708 * but since we are not parsing the main IDL, we don't care about it. 709 * The "true" argument says to search -I directories for the file. 710 */ 711 712 parse(saved_cmd_opt, saved_cmd_val, new_input, true, &int_p); 713 714#if 0 715 if (saved_interface && saved_interface->inherited_interface_name == the_interface->name) { 716 AST_export_n_t * ep = the_interface->exports; 717 AST_export_n_t * op; 718 719 if (AST_OBJECT_SET(the_interface)) { 720 /* ORPC inheritance by pulling in the base class interface's 721 * operations */ 722 saved_interface->op_count = the_interface->op_count; 723 724 for (; ep != NULL; ep = ep->next) { 725 if (ep->kind != AST_operation_k) 726 continue; 727 op = AST_export_node((ASTP_node_t*)ep->thing_p.exported_operation, 728 AST_operation_k); 729 /* Assign the operation number to this operation relative to any 730 * inherited operations */ 731 op->thing_p.exported_operation->op_number = saved_op_count++; 732 saved_interface->exports = (AST_export_n_t*)AST_concat_element( 733 (ASTP_node_t*)saved_interface->exports, 734 (ASTP_node_t*)op 735 ); 736 } 737 /* update the operation count to include base class operations */ 738 saved_interface->op_count = saved_op_count; 739 } 740 } 741#endif 742 743 /* 744 * Restore interface information 745 */ 746 the_interface = saved_interface; 747 748 /* 749 * The recursive parse is done (at this level). 750 * Restore the state machines to the previous values before the import... 751 */ 752 753 /* 754 * Restore information used by error reporting routines. 755 */ 756 ASTP_parsing_main_idl = saved_ASTP_parsing_main_idl; 757 set_name_for_errors(saved_current_file); 758 759 yylineno_p = saved_yylineno_p ; 760 yyin_p = saved_yyin_p; 761 762 return int_p; 763} 764/* 765** p a r s e _ i d l 766** 767** Parse the source IDL file. 768** 769** Side Effects: Returns the interface in the int_p parameters and 770** a boolean status if any errors were encountered. 771*/ 772 773static boolean parse_idl /* Returns true on success */ 774( 775 boolean *cmd_opt, /* [in] Array of command option flags */ 776 void **cmd_val, /* [in] Array of command option values */ 777 STRTAB_str_t idl_sid, /* [in] IDL filespec stringtable ID */ 778 /* STRTAB_NULL_STR => stdin */ 779 AST_interface_n_t **int_p /*[out] Ptr to interface node */ 780) 781 782{ 783 boolean status; /* Status to return */ 784 FE_import_file_n_t *imported_file; /* Main IDL file info */ 785 char const *file_name; /* Main IDL file name */ 786 char imported_fn[max_string_len];/* Main IDL full file name */ 787 struct stat stat_buf; /* File lookup info */ 788 char file_name_part[max_string_len];/* Main IDL file name part */ 789 char file_type_part[max_string_len];/* Main IDL file type part */ 790 boolean name_warning = false; /* Warn on name used */ 791 792 if (idl_sid != STRTAB_NULL_STR) 793 { 794 /* 795 * Record the main IDL as if it is an imported file. 796 * This preserves idempotency in case the main IDL is also imported. 797 */ 798 STRTAB_str_to_string(idl_sid, &file_name); 799 FILE_parse(file_name, NULL, 0, file_name_part, sizeof(file_name_part), file_type_part, sizeof(file_type_part)); 800 strlcat(file_name_part, file_type_part, sizeof(file_name_part)); 801 802 /* 803 * Issue a warning on any system IDL files - a user might 804 * accidentally choose one of those name and get strange behavior. 805 */ 806 if (!strcmp(file_name_part,"iovector.idl")) name_warning = true; 807 else if (!strcmp(file_name_part,"lbase.idl")) name_warning = true; 808 else if (!strcmp(file_name_part,"nbase.idl")) name_warning = true; 809 else if (!strcmp(file_name_part,"ncastat.idl")) name_warning = true; 810 else if (!strcmp(file_name_part,"ndrold.idl")) name_warning = true; 811 else if (!strcmp(file_name_part,"rpc.idl")) name_warning = true; 812 else if (!strcmp(file_name_part,"rpcsts.idl")) name_warning = true; 813 else if (!strcmp(file_name_part,"rpctypes.idl")) name_warning = true; 814 else if (!strcmp(file_name_part,"twr.idl")) name_warning = true; 815 else if (!strcmp(file_name_part,"uuid.idl")) name_warning = true; 816 817 if (name_warning) 818 message_print(NIDL_SYSIDLNAME,file_name); 819 820 /* 821 * Note that a lookup failure will not report a failure here; 822 * That will be reported when we actually try to parse it. 823 */ 824 if (FILE_lookup(file_name, NULL, &stat_buf, imported_fn, sizeof (imported_fn))) 825 { 826 imported_file = NEW (FE_import_file_n_t); 827 imported_file->imported_fn_id = STRTAB_add_string(file_name_part); 828 imported_file->imported_full_fn_id = STRTAB_add_string(imported_fn); 829 imported_file->next = imported_file_list; 830 imported_file_list = imported_file; 831 } 832 } 833 834 /* 835 * Parse the top-level IDL file. The "false" argument tells parse not 836 * to scan the import directories for the source IDL file. 837 */ 838 *int_p = NULL; 839 status = parse(cmd_opt, cmd_val, idl_sid, false, int_p); 840 841 /* Terminate if there were any syntax errors in the top level IDL file. */ 842 if (*int_p == NULL) 843 status = false; 844 845 return status; 846} 847 848/* 849** F E _ m a i n 850** 851** Main frontend routine. Invokes each major frontend component. 852** 853** Note: If cmd_opt[opt_confirm], then no real work is done except to call 854** the components that can issue messages for the verbose option. 855*/ 856 857boolean FE_main /* Returns true on success */ 858( 859 boolean *cmd_opt, /* [in] Array of command option flags */ 860 void **cmd_val, /* [in] Array of command option values */ 861 STRTAB_str_t idl_sid, /* [in] IDL filespec stringtable ID */ 862 /* STRTAB_NULL_STR => stdin */ 863 AST_interface_n_t **int_p /*[out] Ptr to interface node */ 864) 865 866{ 867 boolean status; 868 869 /* Frontend-specific initialization. */ 870 FE_init(); 871 872 /* Parse the source IDL file (and related ACF if applicable). */ 873 status = parse_idl(cmd_opt, cmd_val, idl_sid, int_p); 874 875#ifdef DUMPERS 876 /* Dump the nametable if requested. */ 877 if (cmd_opt[opt_dump_nametbl]) 878 NAMETABLE_dump_tab(); 879#endif 880 881#ifdef DUMPERS 882 /* Dump the AST (before checking) if requested. */ 883 if (cmd_opt[opt_dump_ast]) 884 AST_dump_interface(*int_p); 885#endif 886 887 /* Propagate attributes throughout the AST. */ 888 if (status && !cmd_opt[opt_confirm]) 889 status = PROP_main(cmd_opt, cmd_val, *int_p); 890 891 /* Do semantic checking of the interface. */ 892 if (status) 893 { 894 if (!cmd_opt[opt_confirm]) 895 status = CHECKER_main(cmd_opt, cmd_val, *int_p); 896 } 897 else 898 message_print(NIDL_NOSEMCHECK); 899 900#ifdef DUMPERS 901 /* Dump the AST (after other frontend components) if requested. */ 902 if (cmd_opt[opt_dump_ast_after]) 903 AST_dump_interface(*int_p); 904#endif 905 906 /* Cancel filename for error processing because we are done with source */ 907 set_name_for_errors(NULL); 908 yylineno_p = NULL; 909 yyin_p = NULL; 910 911 return status; 912} 913 914/* preserve coding style vim: set tw=78 sw=4 : */ 915