/* * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Portions of this software have been released under the following terms: * * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION * * To anyone who acknowledges that this file is provided "AS IS" * without any express or implied warranty: * permission to use, copy, modify, and distribute this file for any * purpose is hereby granted without fee, provided that the above * copyright notices and this notice appears in all source code copies, * and that none of the names of Open Software Foundation, Inc., Hewlett- * Packard Company or Digital Equipment Corporation be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Neither Open Software * Foundation, Inc., Hewlett-Packard Company nor Digital * Equipment Corporation makes any representations about the suitability * of this software for any purpose. * * Copyright (c) 2007, Novell, Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Novell Inc. nor the names of its contributors * may be used to endorse or promote products derived from this * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @APPLE_LICENSE_HEADER_END@ */ /* ** ** NAME ** ** FRONTEND.C ** ** FACILITY: ** ** Interface Definition Language (IDL) Compiler ** ** ABSTRACT: ** ** Mainline for IDL compilers. ** ** VERSION: DCE 1.0 ** */ #include <signal.h> #ifdef vms # include <types.h> # include <stat.h> # include <stsdef.h> # include <descrip.h> #else # include <sys/types.h> # include <sys/stat.h> # include <fcntl.h> # include <stdio.h> #endif #include <frontend.h> #include <astp.h> #include <astp_dmp.h> #include <checker.h> #include <command.h> #include <errors.h> #include <files.h> #include <getflags.h> #include <propagat.h> #include <message.h> #define CONFIG_SUFFIX ".acf" /* * Macro to "close" a pipe - don't actually call pclose since it can cause hangs * in certain instances where a parent process opens and closes several pipes, * apparently due to the underlying wait() call from pclose and the unpredict- * ability of the order of child exits. */ #include <errno.h> #define PCLOSE(stream) \ { \ char buf[256]; \ /* Silently read to eof - extra lines should cause COMPABORT msg anyway */ \ while (fgets(buf, sizeof(buf), stream) != NULL) ; \ } /* Globals */ /* Local data definitions. */ static boolean *saved_cmd_opt; /* Array of command option flags */ static void **saved_cmd_val; /* Array of command option values */ typedef struct FE_import_file_n_t { struct FE_import_file_n_t * next; STRTAB_str_t imported_fn_id; STRTAB_str_t imported_full_fn_id; } FE_import_file_n_t; static FE_import_file_n_t * imported_file_list = NULL; extern boolean ASTP_parsing_main_idl; /* * All the error reporting requires a parser location to access line * numbers, etc. However, the APIs are structured such that they may * invoke parser errors even when we are not in the middle of a parse. * In that case, what's the correct line number? Who knows? Let's make * a dummy location and hope we don't get any errors at the wrong time. * -- jpeach */ const parser_location_t empty_parser_location; /* ** i n i t ** ** Frontend-specific initialization. */ static void FE_init(void) { saved_cmd_opt = NULL; saved_cmd_val = NULL; KEYWORDS_init(); NAMETABLE_init(); AST_init(null_parser_location); } /* ** c p p ** ** Sends the source file through CPP before giving it to lex. ** The cpp_output argument is a file ID for the output from cpp. ** UNIX only: cpp_output is connected to piped output from cpp. */ #if defined(CPP) static void cpp ( char *cpp_cmd, /* [in] Base command to invoke cpp */ char *cpp_opt, /* [in] Addtl command options for cpp */ char *file_name, /* [in] Source full filespec; "" => stdin */ char *dst_file_name ATTRIBUTE_UNUSED, /* [in] Target filespec (VMS) */ char **def_strings, /* [in] List of #define's for preprocessor */ char **undef_strings,/* [in] List of #undefine's for preprocessor */ char **idir_list, /* [in] List of -I directories */ FILE **cpp_output /*[out] File ID of cpp output */ ) { char cmd[max_string_len]; /* Command to spawn cpp */ cmd[0] = '\0'; assert(cpp_cmd && *cpp_cmd); /* Put together beginning of command. */ strlcpy(cmd, cpp_cmd, sizeof(cmd)); strlcat(cmd, " ", sizeof(cmd)); strlcat(cmd, cpp_opt ? cpp_opt : "", sizeof(cmd)); strlcat(cmd, " ", sizeof(cmd)); strlcat(cmd, file_name ? file_name : "" , sizeof(cmd)); /* Append the -D strings. */ while (*def_strings) { strlcat(cmd, " -D", sizeof(cmd)); strlcat(cmd, *def_strings++, sizeof(cmd)); } /* Append the -U strings. */ while (*undef_strings) { strlcat(cmd, " -U", sizeof(cmd)); strlcat(cmd, *undef_strings++, sizeof(cmd)); } /* If cpp_cmd is the default, append the -I directories. */ if (strcmp(cpp_cmd, CMD_def_cpp_cmd) == 0) { while (*idir_list) { strlcat(cmd, " -I", sizeof(cmd)); strlcat(cmd, *idir_list++, sizeof(cmd)); } } /* Now execute the cpp command and open output file or pipe. */ if (saved_cmd_opt[opt_verbose]) message_print(NIDL_RUNCPP,cmd); #if 0 printf("CPP - %s\n", cmd); #endif if ((*cpp_output = popen(cmd, "r")) == 0) error(NIDL_INVOKECPP); } #endif /* ** p a r s e _ a c f ** ** Invokes the ACF (Attribute Configuration File) parser on specified file. ** ** Note: If cmd_opt[opt_confirm], then no real work is done except to ** issue messages for the verbose option. ** ** Returns: == 0 => success ** != 0 => failure */ static boolean parse_acf /* Returns true on success */ ( boolean *cmd_opt, /* [in] Array of command option flags */ void **cmd_val, /* [in] Array of command option values */ char *acf_file /* [in] ACF full file name */ ) { FILE * acf_yyin = NULL; char temp_path_name[max_string_len]; /* Full temp file pathname */ void * acf_parser; if (cmd_opt[opt_verbose]) message_print(NIDL_PROCESSACF, acf_file); if (cmd_opt[opt_confirm]) return true; /* * lex & yacc intializations */ acf_parser = acf_parser_alloc(cmd_opt, cmd_val, acf_file); #if defined(CPP) if (cmd_opt[opt_cpp]) { temp_path_name[0] = '\0'; cpp((char *)cmd_val[opt_cpp], (char *)cmd_val[opt_cpp_opt], acf_file, temp_path_name, (char **)cmd_val[opt_cpp_def], (char **)cmd_val[opt_cpp_undef], (char **)cmd_val[opt_idir], &acf_yyin); } else #endif /* No cpp, just open source file */ FILE_open(acf_file, &acf_yyin); acf_parser_input(acf_parser, acf_yyin); if (acf_yyparse(acf_parser) != 0 && acf_errcount(acf_parser) == 0) { log_error(acf_yylineno(acf_parser), NIDL_COMPABORT, NULL); } #if defined(CPP) if (cmd_opt[opt_cpp]) PCLOSE(acf_yyin) else #endif fclose(acf_yyin); if (acf_errcount(acf_parser) != 0) { acf_parser_destroy(acf_parser); return false; } acf_parser_destroy(acf_parser); return true; } /* ** a l r e a d y _ i m p o r t e d ** ** Checks whether a file is already included in the parse or not. ** ** Returns TRUE if the import file has already been parsed. ** Returns false otherwise (Including can't find the file.) ** */ static boolean already_imported ( STRTAB_str_t import_path_id /* The name to check */ ) { char new_import_full_fn[max_string_len]; STRTAB_str_t new_import_full_fn_id; STRTAB_str_t new_import_fn_id; char base_file_name[max_string_len]; char base_file_ext[max_string_len]; struct stat stat_buf; FE_import_file_n_t * imported_file; char const * * idir_list; boolean alr_imp; char const * file_name; /* * Get a string to lookup. */ STRTAB_str_to_string (import_path_id, &file_name); idir_list = (char const * *)saved_cmd_val[opt_idir]; /* * Note that a lookup failure will not report a failure here; * That will be reported when we actually try to import it. */ if (!FILE_lookup(file_name, idir_list, &stat_buf, new_import_full_fn, sizeof (new_import_full_fn))) return false; new_import_full_fn_id = STRTAB_add_string(new_import_full_fn); /* * Make sure there is no partial path information. */ if (!FILE_parse(new_import_full_fn, NULL, 0, base_file_name, sizeof(base_file_name), base_file_ext, sizeof(base_file_ext))) return false; strncat(base_file_name, base_file_ext, max_string_len); new_import_fn_id = STRTAB_add_string(base_file_name); /* * Initialize the default return status. */ alr_imp = false; imported_file = imported_file_list; while ((imported_file != NULL) && (!alr_imp)) { if (new_import_fn_id == imported_file->imported_fn_id) { /* * A match is found in the list. We are done. */ alr_imp = true; } imported_file = imported_file -> next; } /* * Record the import we are about to do if not imported already. */ if (!alr_imp) { imported_file = NEW (FE_import_file_n_t); imported_file -> imported_fn_id = new_import_fn_id; imported_file -> imported_full_fn_id = new_import_full_fn_id; imported_file -> next = imported_file_list; imported_file_list = imported_file; } return alr_imp; } /* ** p a r s e ** ** Invokes the parser on the specified IDL file. If the IDL file is ** successfully parsed, and there is a related ACF file, then the ACF ** file is parsed also. ** ** Returns: a pointer to the interface binding if the IDL file was parsed ** successfully and the ACF file (if any) was parsed successfully; ** NULL otherwise. */ static boolean parse ( boolean *cmd_opt, /* [in] Array of command option flags */ void **cmd_val, /* [in] Array of command option values */ STRTAB_str_t idl_sid, /* [in] IDL filespec stringtable ID */ /* STRTAB_NULL_STR => stdin */ boolean idir_valid, /* [in] true => use import directory list */ AST_interface_n_t **int_p /*[out] Ptr to interface node */ ) { FILE *nidl_yyin = NULL; char const *sf; /* Source filespec */ char full_path_name[max_string_len]; /* Full source pathname */ char temp_path_name[max_string_len]; /* Full temp file pathname */ STRTAB_str_t full_pn_id; /* Full src path string id */ char const * *idir_list; /* List of search directories */ char file_dir[max_string_len]; /* Directory part of src file */ boolean file_dir_is_cwd; /* T => file_dir current dir */ char file_name[max_string_len]; /* File name part of src file */ char acf_file[max_string_len]; /* ACF file name w/o dir */ char full_acf_name[max_string_len]; /* Full ACF pathname */ boolean acf_exists; /* T => ACF file exists */ struct stat stat_buf; /* File lookup stats */ int i=0; void * nidl_parser; /* One-time saving of command array addresses to static storage. */ if (saved_cmd_opt == NULL) saved_cmd_opt = cmd_opt; if (saved_cmd_val == NULL) saved_cmd_val = cmd_val; /* * If the idir_valid flag is set, look in the -I directories for the * source file. Otherwise, just use the filespec as is. */ if (idir_valid) idir_list = (char const * *)cmd_val[opt_idir]; else idir_list = NULL; if (idl_sid == STRTAB_NULL_STR) /* stdin */ full_path_name[0] = '\0'; else { STRTAB_str_to_string(idl_sid, &sf); if (!FILE_lookup(sf, idir_list, &stat_buf, full_path_name, sizeof (full_path_name))) { error(NIDL_FILENOTFND, sf); return false; } } if (cmd_opt[opt_verbose] && !ASTP_parsing_main_idl) message_print(NIDL_IMPORTIDL, full_path_name); #if defined(CPP) if (cmd_opt[opt_cpp]) { temp_path_name[0] = '\0'; /* define the macro describing dceidl compiler (for conditional constructions) */ if (!add_def_string(DCEIDL_DEF)) { message_print(NIDL_INTERNAL_ERROR, "Warning: Couldn't define macro %s!\n", DCEIDL_DEF); } cpp((char *)cmd_val[opt_cpp], (char *)cmd_val[opt_cpp_opt], full_path_name, temp_path_name, (char **)cmd_val[opt_cpp_def], (char **)cmd_val[opt_cpp_undef], (char **)cmd_val[opt_idir], &nidl_yyin); } else #endif if (full_path_name[0] == '\0') /* stdin */ nidl_yyin = stdin; else FILE_open(full_path_name, &nidl_yyin); /* * Setup file name for errors to the full file name */ set_name_for_errors((full_path_name[0] == '\0') ? "stdin" : full_path_name); nidl_parser = nidl_parser_alloc(cmd_opt, cmd_val, full_path_name); nidl_parser_input(nidl_parser, nidl_yyin); #if YYDEBUG && 0 { extern int nidl_yydebug; nidl_yydebug = 1; } #endif if (nidl_yyparse(nidl_parser) != 0 && error_count == 0) log_error(nidl_yylineno(nidl_parser), NIDL_COMPABORT, NULL); *int_p = the_interface; nidl_parser_destroy(nidl_parser); #if defined(CPP) if (cmd_opt[opt_cpp]) PCLOSE(nidl_yyin) else #endif fclose(nidl_yyin); if (error_count != 0) return false; /* Error parsing IDL */ /* Successful parse: save IDL filespec in interface node. */ if (the_interface != NULL) { full_pn_id = STRTAB_add_string(full_path_name); the_interface->fe_info->file = full_pn_id; } else { if (ASTP_parsing_main_idl) return false; /* Shouldn't happen */ } /* * Now see if there is an associated Attribute Configuration File (ACF). * The ACF name is constructed from the IDL file name. The ACF file can * be in any of the -I directories. */ if (!FILE_parse(full_path_name, file_dir, sizeof(file_dir), file_name, sizeof(file_name), (char *)NULL, 0)) return false; if (!FILE_form_filespec(file_name, (char *)NULL, CONFIG_SUFFIX, (char *)NULL, acf_file, sizeof(acf_file))) return false; #ifdef UNIX /* * If the created ACF filespec matches the file_name portion of the IDL * filespec, it implies that the IDL filespec contains multiple '.'s - in * this special case, append the ACF suffix to the filespec. */ if (strcmp(file_name, acf_file) == 0) strlcat(acf_file, CONFIG_SUFFIX, sizeof(acf_file)); #endif /* * If the directory part of the source filespec is not the current dir, * tack it on at the end of the include directory list. Note: we assume * that there is enough room for a temporary extra entry in the idir list. */ idir_list = (char const **)cmd_val[opt_idir]; file_dir_is_cwd = FILE_is_cwd(file_dir); if (!file_dir_is_cwd) { for (i = 0 ; idir_list[i] != NULL ; i++) ; idir_list[i] = file_dir; idir_list[i+1] = NULL; } acf_exists = FILE_lookup(acf_file, idir_list, &stat_buf, full_acf_name, sizeof (full_acf_name)); if (!file_dir_is_cwd) idir_list[i] = NULL; if (!acf_exists) return true; /* No ACF; return success */ /* Parse the ACF. */ if (!parse_acf(cmd_opt, cmd_val, full_acf_name)) return false; /* Error parsing ACF */ return true; /* Both IDL and ACF parsed without errors */ } /* * F E _ p a r s e _ i m p o r t * * Parse an import file. * This involves pushing the state of the current parse, initing a few * cells, calling parse, and restoring the state of the current parse. * * Parametric inputs: The string table id of the filename we wish to parse. * Global inputs: All the parse and lex static storage that maintains parse * state. * Parametric outputs: None * Global outputs: The parse state is restored to its value on entry. * * Routine value: None. */ AST_interface_n_t *FE_parse_import ( STRTAB_str_t new_input /* [in] string table id of file to parse */ ) { /* * BISON/FLEX nester parser support * * FE_parse_import() is called by the import_file rule in * nidl.y. We can be called recursively, for each file requested * to be included. To support this with non-reentrant Flex * and Bison parsers, we save the current Flex/Bison state, * create a new, initialized state for the ACF & NIDL x Flex & BISON * state machines, and parse the import. When we are done, * we delete the temporary parsers states used to do the import, * and restore the parser state variables back to where they were. * * The support logic to do context switching of parser state machines * can be found at the end of nidl.l, nidl.y, acf.l, acf.y * * For any given import, we have to save and reset FOUR different * state machines: * * ACF parser, ACF flexxer, NIDL parser, NIDL lexxer * */ boolean saved_ASTP_parsing_main_idl; char saved_current_file[ PATH_MAX ]; AST_interface_n_t *int_p; unsigned * saved_yylineno_p = yylineno_p; FILE * saved_yyin_p = yyin_p; /* Saved interface attributes */ AST_interface_n_t *saved_interface; #if 0 int saved_op_count; #endif /* * Return now, if the file is already imported. */ if (already_imported (new_input)) return (AST_interface_n_t *)NULL; /* save the AST state */ saved_ASTP_parsing_main_idl = ASTP_parsing_main_idl; inq_name_for_errors(saved_current_file, sizeof (saved_current_file)); /* * Save interface information */ saved_interface = the_interface; #if 0 saved_op_count = the_interface ? the_interface->op_count : 0; #endif /* * Initialize interface attributes */ the_interface = NULL; /* * We have now saved away all the state of the current parse. * Initialize a few cells, open the imported file and recursively invoke the * parse. */ if (saved_interface) ASTP_parsing_main_idl = false; /* * Create new, empty and initialized parser context to * do the import. */ /* Now we can parse the import file.... * Parse the file. Routine parse normally returns a AST_interface_n_t, * but since we are not parsing the main IDL, we don't care about it. * The "true" argument says to search -I directories for the file. */ parse(saved_cmd_opt, saved_cmd_val, new_input, true, &int_p); #if 0 if (saved_interface && saved_interface->inherited_interface_name == the_interface->name) { AST_export_n_t * ep = the_interface->exports; AST_export_n_t * op; if (AST_OBJECT_SET(the_interface)) { /* ORPC inheritance by pulling in the base class interface's * operations */ saved_interface->op_count = the_interface->op_count; for (; ep != NULL; ep = ep->next) { if (ep->kind != AST_operation_k) continue; op = AST_export_node((ASTP_node_t*)ep->thing_p.exported_operation, AST_operation_k); /* Assign the operation number to this operation relative to any * inherited operations */ op->thing_p.exported_operation->op_number = saved_op_count++; saved_interface->exports = (AST_export_n_t*)AST_concat_element( (ASTP_node_t*)saved_interface->exports, (ASTP_node_t*)op ); } /* update the operation count to include base class operations */ saved_interface->op_count = saved_op_count; } } #endif /* * Restore interface information */ the_interface = saved_interface; /* * The recursive parse is done (at this level). * Restore the state machines to the previous values before the import... */ /* * Restore information used by error reporting routines. */ ASTP_parsing_main_idl = saved_ASTP_parsing_main_idl; set_name_for_errors(saved_current_file); yylineno_p = saved_yylineno_p ; yyin_p = saved_yyin_p; return int_p; } /* ** p a r s e _ i d l ** ** Parse the source IDL file. ** ** Side Effects: Returns the interface in the int_p parameters and ** a boolean status if any errors were encountered. */ static boolean parse_idl /* Returns true on success */ ( boolean *cmd_opt, /* [in] Array of command option flags */ void **cmd_val, /* [in] Array of command option values */ STRTAB_str_t idl_sid, /* [in] IDL filespec stringtable ID */ /* STRTAB_NULL_STR => stdin */ AST_interface_n_t **int_p /*[out] Ptr to interface node */ ) { boolean status; /* Status to return */ FE_import_file_n_t *imported_file; /* Main IDL file info */ char const *file_name; /* Main IDL file name */ char imported_fn[max_string_len];/* Main IDL full file name */ struct stat stat_buf; /* File lookup info */ char file_name_part[max_string_len];/* Main IDL file name part */ char file_type_part[max_string_len];/* Main IDL file type part */ boolean name_warning = false; /* Warn on name used */ if (idl_sid != STRTAB_NULL_STR) { /* * Record the main IDL as if it is an imported file. * This preserves idempotency in case the main IDL is also imported. */ STRTAB_str_to_string(idl_sid, &file_name); FILE_parse(file_name, NULL, 0, file_name_part, sizeof(file_name_part), file_type_part, sizeof(file_type_part)); strlcat(file_name_part, file_type_part, sizeof(file_name_part)); /* * Issue a warning on any system IDL files - a user might * accidentally choose one of those name and get strange behavior. */ if (!strcmp(file_name_part,"iovector.idl")) name_warning = true; else if (!strcmp(file_name_part,"lbase.idl")) name_warning = true; else if (!strcmp(file_name_part,"nbase.idl")) name_warning = true; else if (!strcmp(file_name_part,"ncastat.idl")) name_warning = true; else if (!strcmp(file_name_part,"ndrold.idl")) name_warning = true; else if (!strcmp(file_name_part,"rpc.idl")) name_warning = true; else if (!strcmp(file_name_part,"rpcsts.idl")) name_warning = true; else if (!strcmp(file_name_part,"rpctypes.idl")) name_warning = true; else if (!strcmp(file_name_part,"twr.idl")) name_warning = true; else if (!strcmp(file_name_part,"uuid.idl")) name_warning = true; if (name_warning) message_print(NIDL_SYSIDLNAME,file_name); /* * Note that a lookup failure will not report a failure here; * That will be reported when we actually try to parse it. */ if (FILE_lookup(file_name, NULL, &stat_buf, imported_fn, sizeof (imported_fn))) { imported_file = NEW (FE_import_file_n_t); imported_file->imported_fn_id = STRTAB_add_string(file_name_part); imported_file->imported_full_fn_id = STRTAB_add_string(imported_fn); imported_file->next = imported_file_list; imported_file_list = imported_file; } } /* * Parse the top-level IDL file. The "false" argument tells parse not * to scan the import directories for the source IDL file. */ *int_p = NULL; status = parse(cmd_opt, cmd_val, idl_sid, false, int_p); /* Terminate if there were any syntax errors in the top level IDL file. */ if (*int_p == NULL) status = false; return status; } /* ** F E _ m a i n ** ** Main frontend routine. Invokes each major frontend component. ** ** Note: If cmd_opt[opt_confirm], then no real work is done except to call ** the components that can issue messages for the verbose option. */ boolean FE_main /* Returns true on success */ ( boolean *cmd_opt, /* [in] Array of command option flags */ void **cmd_val, /* [in] Array of command option values */ STRTAB_str_t idl_sid, /* [in] IDL filespec stringtable ID */ /* STRTAB_NULL_STR => stdin */ AST_interface_n_t **int_p /*[out] Ptr to interface node */ ) { boolean status; /* Frontend-specific initialization. */ FE_init(); /* Parse the source IDL file (and related ACF if applicable). */ status = parse_idl(cmd_opt, cmd_val, idl_sid, int_p); #ifdef DUMPERS /* Dump the nametable if requested. */ if (cmd_opt[opt_dump_nametbl]) NAMETABLE_dump_tab(); #endif #ifdef DUMPERS /* Dump the AST (before checking) if requested. */ if (cmd_opt[opt_dump_ast]) AST_dump_interface(*int_p); #endif /* Propagate attributes throughout the AST. */ if (status && !cmd_opt[opt_confirm]) status = PROP_main(cmd_opt, cmd_val, *int_p); /* Do semantic checking of the interface. */ if (status) { if (!cmd_opt[opt_confirm]) status = CHECKER_main(cmd_opt, cmd_val, *int_p); } else message_print(NIDL_NOSEMCHECK); #ifdef DUMPERS /* Dump the AST (after other frontend components) if requested. */ if (cmd_opt[opt_dump_ast_after]) AST_dump_interface(*int_p); #endif /* Cancel filename for error processing because we are done with source */ set_name_for_errors(NULL); yylineno_p = NULL; yyin_p = NULL; return status; } /* preserve coding style vim: set tw=78 sw=4 : */