Changeset 108284 in vbox
- Timestamp:
- Feb 19, 2025 10:50:10 AM (2 months ago)
- svn:sync-xref-src-repo-rev:
- 167627
- Location:
- trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl.c
r108268 r108284 45 45 static ModeData modes[] = { 46 46 {"header", "Generate C++ header", "h", xpidl_header_dispatch}, 47 {"typelib", "Generate XPConnect typelib", "xpt", xpidl_typelib_dispatch}, 47 /* {"typelib", "Generate XPConnect typelib", "xpt", xpidl_typelib_dispatch},*/ 48 48 {0, 0, 0, 0} 49 49 }; … … 60 60 } 61 61 62 gboolean enable_debug = FALSE;63 gboolean enable_warnings = FALSE;64 gboolean verbose_mode = FALSE;65 gboolean emit_typelib_annotations = FALSE;66 gboolean explicit_output_filename = FALSE;62 bool enable_debug = false; 63 bool enable_warnings = false; 64 bool verbose_mode = false; 65 bool emit_typelib_annotations = false; 66 bool explicit_output_filename = false; 67 67 68 68 /* The following globals are explained in xpt_struct.h */ … … 98 98 99 99 int i; 100 IncludePathEntry *inc, *inc_head, **inc_tail;100 RTLISTANCHOR LstIncludePaths; 101 101 char *file_basename = NULL; 102 102 ModeData *mode = NULL; 103 gboolean create_old_typelib = FALSE; 104 105 /* turn this on for extra checking of our code */ 106 /* IDL_check_cast_enable(TRUE); */ 107 108 inc_head = xpidl_malloc(sizeof *inc); 109 inc_head->directory = "."; 110 inc_head->next = NULL; 111 inc_tail = &inc_head->next; 103 104 RTListInit(&LstIncludePaths); 105 106 PXPIDLINCLUDEDIR pInc = (PXPIDLINCLUDEDIR)xpidl_malloc(sizeof(*pInc)); 107 pInc->pszPath = "."; 108 RTListAppend(&LstIncludePaths, &pInc->NdIncludes); 112 109 113 110 for (i = 1; i < argc; i++) { … … 121 118 goto done_options; 122 119 case 'a': 123 emit_typelib_annotations = TRUE;120 emit_typelib_annotations = true; 124 121 break; 125 122 case 'w': 126 enable_warnings = TRUE;123 enable_warnings = true; 127 124 break; 128 125 case 'v': 129 verbose_mode = TRUE;126 verbose_mode = true; 130 127 break; 131 128 case 't': … … 141 138 if (i + 1 == argc) { 142 139 fprintf(stderr, "ERROR: missing version number after -t\n"); 143 xpidl_usage(argc, argv);144 return 1;145 }146 147 /* Do not allow more than one "-t" definition */148 if (create_old_typelib) {149 fprintf(stderr,150 "ERROR: -t argument used twice. "151 "Cannot specify more than one version\n");152 140 xpidl_usage(argc, argv); 153 141 return 1; … … 164 152 break; 165 153 case XPT_VERSION_OLD: 166 create_old_typelib = TRUE;167 break;168 154 case XPT_VERSION_UNSUPPORTED: 169 155 fprintf(stderr, "ERROR: version \"%s\" not supported.\n", … … 186 172 return 1; 187 173 } 188 inc = xpidl_malloc(sizeof *inc);174 pInc = (PXPIDLINCLUDEDIR)xpidl_malloc(sizeof(*pInc)); 189 175 if (argv[i][2] == '\0') { 190 176 /* is it the -I foo form? */ 191 inc->directory= argv[++i];177 pInc->pszPath = argv[++i]; 192 178 } else { 193 179 /* must be the -Ifoo form. Don't preincrement i. */ 194 inc->directory = argv[i] + 2; 195 } 196 #ifdef DEBUG_shaver_includes 197 fprintf(stderr, "adding %s to include path\n", inc->directory); 198 #endif 199 inc->next = NULL; 200 *inc_tail = inc; 201 inc_tail = &inc->next; 180 pInc->pszPath = argv[i] + 2; 181 } 182 183 RTListAppend(&LstIncludePaths, &pInc->NdIncludes); 202 184 break; 203 185 case 'o': … … 208 190 } 209 191 file_basename = argv[++i]; 210 explicit_output_filename = FALSE;192 explicit_output_filename = false; 211 193 break; 212 194 case 'e': … … 217 199 } 218 200 file_basename = argv[++i]; 219 explicit_output_filename = TRUE;201 explicit_output_filename = true; 220 202 break; 221 203 case 'm': … … 260 242 * multiply. 261 243 */ 262 if (xpidl_process_idl(argv[i], inc_head, file_basename, mode))244 if (xpidl_process_idl(argv[i], &LstIncludePaths, file_basename, mode)) 263 245 return 0; 246 247 /** @todo Free include paths. */ 264 248 265 249 return 1; -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl.h
r108268 r108284 43 43 #define __xpidl_h 44 44 45 #include <iprt/errcore.h> 46 #include <iprt/list.h> 47 #include <iprt/script.h> 48 45 49 #include <errno.h> 46 50 #include <stddef.h> 47 51 #include <stdio.h> 48 52 #include <stdlib.h> 49 #include <glib.h> 50 #include <string.h> /* After glib.h to avoid warnings about shadowing 'index'. */ 51 52 #ifndef XP_MAC 53 #include <libIDL/IDL.h> 54 #else 55 #include <IDL.h> 56 #endif 53 #include <string.h> 57 54 58 55 #include <xpt_struct.h> 59 56 60 #define XPIDL_WARNING(x) IDL_tree_warning x 57 58 /** 59 * An include path. 60 */ 61 typedef struct XPIDLINCLUDEDIR 62 { 63 /** Node for the list of include paths. */ 64 RTLISTNODE NdIncludes; 65 /** The zero terminated include path. */ 66 const char *pszPath; 67 } XPIDLINCLUDEDIR; 68 /** Pointer to an include path. */ 69 typedef XPIDLINCLUDEDIR *PXPIDLINCLUDEDIR; 70 /** Pointer to a const include path. */ 71 typedef const XPIDLINCLUDEDIR *PCXPIDLINCLUDEDIR; 72 73 74 /** 75 * The input stream. 76 */ 77 typedef struct XPIDLINPUT 78 { 79 /** Node for the list of inputs. */ 80 RTLISTNODE NdInput; 81 /** The list of includes this input generated. */ 82 RTLISTANCHOR LstIncludes; 83 /** The basename for this input. */ 84 char *pszBasename; 85 /** The filename for this input. */ 86 char *pszFilename; 87 /** The lexer instance for this input. */ 88 RTSCRIPTLEX hIdlLex; 89 } XPIDLINPUT; 90 /** Pointer to an input stream. */ 91 typedef XPIDLINPUT *PXPIDLINPUT; 92 /** Pointer to a const input stream. */ 93 typedef const XPIDLINPUT *PCXPIDLINPUT; 94 95 96 /** 97 * IDL node type. 98 */ 99 typedef enum XPIDLNDTYPE 100 { 101 kXpidlNdType_Invalid = 0, 102 kXpidlNdType_RawBlock, 103 kXpidlNdType_Typedef, 104 kXpidlNdType_Native, 105 kXpidlNdType_Interface, 106 kXpidlNdType_Forward_Decl 107 } XPIDLNDTYPE; 108 109 110 /** 111 * A node attribute. 112 */ 113 typedef struct XPIDLATTR 114 { 115 /** The attribute name. */ 116 const char *pszName; 117 /** The value assigned if any. */ 118 const char *pszVal; 119 } XPIDLATTR; 120 /** Pointer to an attribute. */ 121 typedef XPIDLATTR *PXPIDLATTR; 122 /** Pointer to a const attribute. */ 123 typedef const XPIDLATTR *PCXPIDLATTR; 124 125 126 /** Pointer to an IDL node. */ 127 typedef struct XPIDLNODE *PXPIDLNODE; 128 /** Pointer to a const IDL node. */ 129 typedef const struct XPIDLNODE *PCXPIDLNODE; 130 131 /** 132 * IDL node. 133 */ 134 typedef struct XPIDLNODE 135 { 136 /** Node for the list this node is in. */ 137 RTLISTNODE NdLst; 138 /** The parent node (if any). */ 139 PCXPIDLNODE pParent; 140 /** The input stream this node was generated from (via #include's). */ 141 PCXPIDLINPUT pInput; 142 /** The node type. */ 143 XPIDLNDTYPE enmType; 144 /** Node type dependent data. */ 145 union 146 { 147 struct 148 { 149 const char *pszRaw; 150 size_t cchRaw; 151 } RawBlock; 152 } u; 153 } XPIDLNODE; 154 155 156 /** 157 * The IDL parsing state. 158 */ 159 typedef struct XPIDLPARSE 160 { 161 /** List of input files. */ 162 RTLISTANCHOR LstInputs; 163 /** The list of XPIDL nodes from the root. */ 164 RTLISTANCHOR LstNodes; 165 /** Extended error info. */ 166 RTERRINFOSTATIC ErrInfo; 167 } XPIDLPARSE; 168 /** Pointer to an IDL parsing state. */ 169 typedef XPIDLPARSE *PXPIDLPARSE; 170 /** Pointer to a const IDL parsing state. */ 171 typedef const XPIDLPARSE *PCXPIDLPARSE; 172 61 173 62 174 /* 63 175 * Internal operation flags. 64 176 */ 65 extern gbooleanenable_debug;66 extern gbooleanenable_warnings;67 extern gbooleanverbose_mode;68 extern gbooleanemit_typelib_annotations;69 extern gbooleanexplicit_output_filename;177 extern bool enable_debug; 178 extern bool enable_warnings; 179 extern bool verbose_mode; 180 extern bool emit_typelib_annotations; 181 extern bool explicit_output_filename; 70 182 71 183 extern PRUint8 major_version; … … 77 189 * A function to handle an IDL_tree type. 78 190 */ 79 typedef gboolean(*nodeHandler)(TreeState *);191 typedef bool (*nodeHandler)(TreeState *); 80 192 81 193 /* … … 93 205 extern backend *xpidl_header_dispatch(void); 94 206 extern backend *xpidl_typelib_dispatch(void); 95 extern backend *xpidl_doc_dispatch(void);96 extern backend *xpidl_java_dispatch(void);97 207 98 208 typedef struct ModeData { … … 103 213 } ModeData; 104 214 105 typedef struct IncludePathEntry {106 char *directory;107 struct IncludePathEntry *next;108 } IncludePathEntry;109 215 110 216 struct TreeState { … … 112 218 /* Maybe supplied by -o. Not related to (g_)basename from string.h or glib */ 113 219 char *basename; 114 IDL_ns ns; 115 IDL_tree tree; 116 GSList *base_includes; 220 RTLISTANCHOR *base_includes; 117 221 nodeHandler *dispatch; 118 222 void *priv; /* mode-private data */ … … 124 228 */ 125 229 int 126 xpidl_process_idl(char *filename, IncludePathEntry *include_path,230 xpidl_process_idl(char *filename, PRTLISTANCHOR pLstIncludePaths, 127 231 char *file_basename, ModeData *mode); 128 129 /*130 * Iterate over an IDLN_LIST -- why is this not part of libIDL?131 */132 void133 xpidl_list_foreach(IDL_tree p, IDL_tree_func foreach, gpointer user_data);134 232 135 233 /* … … 152 250 * Process an XPIDL node and its kids, if any. 153 251 */ 154 gboolean 252 bool 155 253 xpidl_process_node(TreeState *state); 156 254 … … 177 275 * UUID_LENGTH bytes. 178 276 */ 179 gboolean 277 bool 180 278 xpidl_sprint_iid(nsID *iid, char iidbuf[]); 181 279 … … 184 282 * so we re-implement nsID::Parse here. 185 283 */ 186 gboolean 284 bool 187 285 xpidl_parse_iid(nsID *id, const char *str); 188 286 189 287 288 #if 0 190 289 /* Try to common a little node-handling stuff. */ 191 290 … … 253 352 void 254 353 printlist(FILE *outfile, GSList *slist); 354 #endif 255 355 256 356 #endif /* __xpidl_h */ -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl_header.c
r108268 r108284 47 47 #define AS_IMPL 2 48 48 49 static gboolean write_method_signature(IDL_tree method_tree, FILE *outfile, 49 #if 0 50 static bool write_method_signature(IDL_tree method_tree, FILE *outfile, 50 51 int mode, const char *className); 51 static gbooleanwrite_attr_accessor(IDL_tree attr_tree, FILE * outfile,52 gbooleangetter,52 static bool write_attr_accessor(IDL_tree attr_tree, FILE * outfile, 53 bool getter, 53 54 int mode, const char *className); 54 55 … … 58 59 } 59 60 60 static gboolean61 static bool 61 62 header_prolog(TreeState *state) 62 63 { … … 115 116 } 116 117 117 static gboolean118 static bool 118 119 header_epilog(TreeState *state) 119 120 { … … 140 141 } 141 142 142 static gboolean143 static bool 143 144 interface(TreeState *state) 144 145 { … … 147 148 char *classNameUpper = NULL; 148 149 char *cp; 149 gbooleanok = TRUE;150 gbooleankeepvtable;150 bool ok = TRUE; 151 bool keepvtable; 151 152 const char *iid; 152 153 const char *name_space; … … 488 489 } 489 490 490 static gboolean491 static bool 491 492 list(TreeState *state) 492 493 { … … 500 501 } 501 502 502 static gboolean503 write_type(IDL_tree type_tree, gbooleanis_out, FILE *outfile)503 static bool 504 write_type(IDL_tree type_tree, bool is_out, FILE *outfile) 504 505 { 505 506 if (!type_tree) { … … 510 511 switch (IDL_NODE_TYPE(type_tree)) { 511 512 case IDLN_TYPE_INTEGER: { 512 gbooleansign = IDL_TYPE_INTEGER(type_tree).f_signed;513 bool sign = IDL_TYPE_INTEGER(type_tree).f_signed; 513 514 switch (IDL_TYPE_INTEGER(type_tree).f_type) { 514 515 case IDL_INTEGER_TYPE_SHORT: … … 610 611 * AS_CALL writes 'foo(bar, sil)' 611 612 */ 612 static gboolean613 static bool 613 614 write_attr_accessor(IDL_tree attr_tree, FILE * outfile, 614 gbooleangetter, int mode, const char *className)615 bool getter, int mode, const char *className) 615 616 { 616 617 char *attrname = ATTR_IDENT(attr_tree).str; … … 650 651 } 651 652 652 static gboolean653 static bool 653 654 attr_dcl(TreeState *state) 654 655 { … … 696 697 } 697 698 698 static gboolean699 static bool 699 700 do_enum(TreeState *state) 700 701 { … … 704 705 } 705 706 706 static gboolean707 static bool 707 708 do_const_dcl(TreeState *state) 708 709 { 709 710 struct _IDL_CONST_DCL *dcl = &IDL_CONST_DCL(state->tree); 710 711 const char *name = IDL_IDENT(dcl->ident).str; 711 gbooleanis_signed;712 bool is_signed; 712 713 GSList *doc_comments = IDL_IDENT(dcl->ident).comments; 713 714 IDL_tree real_type; … … 736 737 } 737 738 738 static gboolean739 static bool 739 740 do_typedef(TreeState *state) 740 741 { … … 795 796 796 797 /* If notype is true, just write the param name. */ 797 static gboolean798 static bool 798 799 write_param(IDL_tree param_tree, FILE *outfile) 799 800 { 800 801 IDL_tree param_type_spec = IDL_PARAM_DCL(param_tree).param_type_spec; 801 gbooleanis_in = IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_IN;802 bool is_in = IDL_PARAM_DCL(param_tree).attr == IDL_PARAM_IN; 802 803 /* in string, wstring, nsid, domstring, utf8string, cstring and 803 804 * astring any explicitly marked [const] are const … … 850 851 * A forward declaration, usually an interface. 851 852 */ 852 static gboolean853 static bool 853 854 forward_dcl(TreeState *state) 854 855 { … … 871 872 * AS_CALL writes 'foo(bar, sil)' 872 873 */ 873 static gboolean874 static bool 874 875 write_method_signature(IDL_tree method_tree, FILE *outfile, int mode, 875 876 const char *className) 876 877 { 877 878 struct _IDL_OP_DCL *op = &IDL_OP_DCL(method_tree); 878 gbooleanno_generated_args = TRUE;879 gbooleanop_notxpcom =879 bool no_generated_args = TRUE; 880 bool op_notxpcom = 880 881 (IDL_tree_property_get(op->ident, "notxpcom") != NULL); 881 882 const char *name; … … 969 970 * I blame Elliot. 970 971 */ 971 static gboolean972 static bool 972 973 op_dcl(TreeState *state) 973 974 { … … 1004 1005 } 1005 1006 1006 static gboolean1007 static bool 1007 1008 codefrag(TreeState *state) 1008 1009 { … … 1030 1031 return TRUE; 1031 1032 } 1033 #endif 1032 1034 1033 1035 backend * … … 1035 1037 { 1036 1038 static backend result; 1037 static nodeHandler table[ IDLN_LAST];1038 static gboolean initialized = FALSE;1039 static nodeHandler table[10 /*IDLN_LAST*/]; 1040 static bool initialized = false; 1039 1041 1040 result.emit_prolog = header_prolog; 1041 result.emit_epilog = header_epilog; 1042 1042 result.emit_prolog = NULL; //header_prolog; 1043 result.emit_epilog = NULL; //header_epilog; 1044 1045 #if 0 1043 1046 if (!initialized) { 1044 table[IDLN_LIST] = list; 1045 table[IDLN_ATTR_DCL] = attr_dcl; 1046 table[IDLN_OP_DCL] = op_dcl; 1047 table[IDLN_FORWARD_DCL] = forward_dcl; 1048 table[IDLN_TYPE_ENUM] = do_enum; 1049 table[IDLN_INTERFACE] = interface; 1050 table[IDLN_CODEFRAG] = codefrag; 1051 table[IDLN_TYPE_DCL] = do_typedef; 1052 table[IDLN_CONST_DCL] = do_const_dcl; 1053 table[IDLN_NATIVE] = check_native; 1054 initialized = TRUE; 1055 } 1047 table[IDLN_LIST] = NULL; //list; 1048 table[IDLN_ATTR_DCL] = NULL; //attr_dcl; 1049 table[IDLN_OP_DCL] = NULL; //op_dcl; 1050 table[IDLN_FORWARD_DCL] = NULL; //forward_dcl; 1051 table[IDLN_TYPE_ENUM] = NULL; //do_enum; 1052 table[IDLN_INTERFACE] = NULL; //interface; 1053 table[IDLN_CODEFRAG] = NULL; //codefrag; 1054 table[IDLN_TYPE_DCL] = NULL; //do_typedef; 1055 table[IDLN_CONST_DCL] = NULL; //do_const_dcl; 1056 table[IDLN_NATIVE] = NULL; //check_native; 1057 initialized = true; 1058 } 1059 #endif 1056 1060 1057 1061 result.dispatch_table = table; -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl_idl.c
r108268 r108284 1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* ***** BEGIN LICENSE BLOCK ***** 3 * Version: NPL 1.1/GPL 2.0/LGPL 2.1 4 * 5 * The contents of this file are subject to the Netscape Public License 6 * Version 1.1 (the "License"); you may not use this file except in 7 * compliance with the License. You may obtain a copy of the License at 8 * http://www.mozilla.org/NPL/ 9 * 10 * Software distributed under the License is distributed on an "AS IS" basis, 11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 * for the specific language governing rights and limitations under the 1 /* $Id$ */ 2 /** @file 3 * VBox xpidl clone - IDL parsing. 4 */ 5 6 /* 7 * Copyright (C) 2025 Oracle and/or its affiliates. 8 * 9 * This file is part of VirtualBox base platform packages, as 10 * available from https://www.virtualbox.org. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation, in version 3 of the 13 15 * License. 14 16 * 15 * The Original Code is mozilla.org code. 16 * 17 * The Initial Developer of the Original Code is 18 * Netscape Communications Corporation. 19 * Portions created by the Initial Developer are Copyright (C) 1998 20 * the Initial Developer. All Rights Reserved. 21 * 22 * Contributor(s): 23 * Michael Ang <[email protected]> 24 * 25 * Alternatively, the contents of this file may be used under the terms of 26 * either the GNU General Public License Version 2 or later (the "GPL"), or 27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 * in which case the provisions of the GPL or the LGPL are applicable instead 29 * of those above. If you wish to allow use of your version of this file only 30 * under the terms of either the GPL or the LGPL, and not to allow others to 31 * use your version of this file under the terms of the NPL, indicate your 32 * decision by deleting the provisions above and replace them with the notice 33 * and other provisions required by the GPL or the LGPL. If you do not delete 34 * the provisions above, a recipient may use your version of this file under 35 * the terms of any one of the NPL, the GPL or the LGPL. 36 * 37 * ***** END LICENSE BLOCK ***** */ 38 39 /* 40 * Common IDL-processing code. 17 * This program is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, see <https://www.gnu.org/licenses>. 24 * 25 * SPDX-License-Identifier: GPL-3.0-only 41 26 */ 42 27 #include <iprt/errcore.h> 43 28 #include <iprt/file.h> 44 29 #include <iprt/mem.h> 30 #include <iprt/message.h> 31 #include <iprt/path.h> 32 #include <iprt/stream.h> 33 #include <iprt/string.h> 45 34 46 35 #include "xpidl.h" 47 36 48 static gboolean parsed_empty_file; 49 50 /* 51 * The bulk of the generation happens here. 37 38 typedef enum XPIDLKEYWORD 39 { 40 kXpidlKeyword_Invalid = 0, 41 kXpidlKeyword_Include, 42 kXpidlKeyword_Typedef, 43 kXpidlKeyword_32Bit_Hack = 0x7fffffff 44 } XPIDLKEYWORD; 45 46 static DECLCALLBACK(int) xpidlIdlLexParseNumberIdentifierOrUuid(RTSCRIPTLEX hScriptLex, char ch, PRTSCRIPTLEXTOKEN pToken, void *pvUser); 47 48 49 static const char *s_aszSingleStart[] = 50 { 51 "//", 52 NULL 53 }; 54 55 56 static const char *s_aszMultiStart[] = 57 { 58 "/*", 59 "%{C++", 60 NULL 61 }; 62 63 64 static const char *s_aszMultiEnd[] = 65 { 66 "*/", 67 "%}", 68 NULL 69 }; 70 71 72 static const RTSCRIPTLEXTOKMATCH s_aMatches[] = 73 { 74 { RT_STR_TUPLE("#include"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, kXpidlKeyword_Include }, 75 { RT_STR_TUPLE("uuid"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 76 { RT_STR_TUPLE("ptr"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 77 { RT_STR_TUPLE("ref"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 78 { RT_STR_TUPLE("in"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 79 { RT_STR_TUPLE("out"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 80 { RT_STR_TUPLE("scriptable"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 81 { RT_STR_TUPLE("noscript"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 82 { RT_STR_TUPLE("array"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 83 { RT_STR_TUPLE("size_is"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 84 { RT_STR_TUPLE("readonly"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 85 { RT_STR_TUPLE("attribute"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 86 { RT_STR_TUPLE("retval"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 87 { RT_STR_TUPLE("interface"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 88 { RT_STR_TUPLE("const"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 89 { RT_STR_TUPLE("native"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 90 { RT_STR_TUPLE("nsid"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, 0 }, 91 { RT_STR_TUPLE("typedef"), RTSCRIPTLEXTOKTYPE_KEYWORD, true, kXpidlKeyword_Typedef }, 92 93 { RT_STR_TUPLE(","), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, ',' }, 94 { RT_STR_TUPLE("["), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, '[' }, 95 { RT_STR_TUPLE("]"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, ']' }, 96 { RT_STR_TUPLE("{"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, '{' }, 97 { RT_STR_TUPLE("}"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, '}' }, 98 { RT_STR_TUPLE("("), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, '(' }, 99 { RT_STR_TUPLE(")"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, ')' }, 100 { RT_STR_TUPLE(";"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, ';' }, 101 { RT_STR_TUPLE("="), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, '=' }, 102 { RT_STR_TUPLE(":"), RTSCRIPTLEXTOKTYPE_PUNCTUATOR, false, ':' }, 103 { NULL, 0, RTSCRIPTLEXTOKTYPE_INVALID, false, 0 } 104 }; 105 106 107 static const RTSCRIPTLEXRULE s_aRules[] = 108 { 109 { '\"', '\"', RTSCRIPT_LEX_RULE_CONSUME, RTScriptLexScanStringLiteralC, NULL}, /** @todo This is not correct. */ 110 { '0', '9', RTSCRIPT_LEX_RULE_DEFAULT, xpidlIdlLexParseNumberIdentifierOrUuid, NULL}, 111 { 'a', 'z', RTSCRIPT_LEX_RULE_DEFAULT, xpidlIdlLexParseNumberIdentifierOrUuid, NULL}, 112 { 'A', 'Z', RTSCRIPT_LEX_RULE_DEFAULT, xpidlIdlLexParseNumberIdentifierOrUuid, NULL}, 113 { '_', '_', RTSCRIPT_LEX_RULE_DEFAULT, RTScriptLexScanIdentifier, NULL}, 114 { '\0', '\0', RTSCRIPT_LEX_RULE_DEFAULT, NULL, NULL} 115 }; 116 117 118 static const RTSCRIPTLEXCFG g_IdlLexCfg = 119 { 120 /** pszName */ 121 "IDL", 122 /** pszDesc */ 123 "IDL lexer", 124 /** fFlags */ 125 RTSCRIPT_LEX_CFG_F_COMMENTS_AS_TOKENS, 126 /** pszWhitespace */ 127 NULL, 128 /** pszNewline */ 129 NULL, 130 /** papszCommentMultiStart */ 131 s_aszMultiStart, 132 /** papszCommentMultiEnd */ 133 s_aszMultiEnd, 134 /** papszCommentSingleStart */ 135 s_aszSingleStart, 136 /** paTokMatches */ 137 s_aMatches, 138 /** paRules */ 139 s_aRules, 140 /** pfnProdDef */ 141 NULL, 142 /** pfnProdDefUser */ 143 NULL 144 }; 145 146 147 static bool g_fRequiredUuid = false; 148 149 static int xpidlParseIdl(PXPIDLPARSE pThis, PXPIDLINPUT pInput, PRTLISTANCHOR pLstIncludePaths); 150 151 152 static DECLCALLBACK(int) xpidlIdlLexParseNumberIdentifierOrUuid(RTSCRIPTLEX hScriptLex, char ch, PRTSCRIPTLEXTOKEN pToken, void *pvUser) 153 { 154 RT_NOREF(pvUser); 155 if (g_fRequiredUuid) 156 { 157 g_fRequiredUuid = false; 158 /* Scan as an identifier. */ 159 static const char *g_aszIdeCharSetUuid = "abcdefABCDEF01234567809-"; 160 RTScriptLexConsumeCh(hScriptLex); 161 return RTScriptLexScanIdentifier(hScriptLex, ch, pToken, (void *)g_aszIdeCharSetUuid); 162 } 163 else if (ch >= '0' && ch <= '9') 164 return RTScriptLexScanNumber(hScriptLex, 0 /*uBase*/, false /*fAllowReal*/, pToken); 165 166 RTScriptLexConsumeCh(hScriptLex); 167 return RTScriptLexScanIdentifier(hScriptLex, ch, pToken, NULL); 168 } 169 170 171 /** 172 * Create a new lexer from the given filename, possibly searching the include paths. 173 * 174 * @returns IPRT status code. 175 * @param pszFilename The filename to read. 176 * @param pLstIncludePaths The list of include paths to search for relative filenames. 177 * @param phIdlLex Where to store the handle to the lexer on success. 52 178 */ 53 gboolean 54 xpidl_process_node(TreeState *state) 55 { 56 gint type; 57 nodeHandler *dispatch, handler; 58 59 XPT_ASSERT(state->tree); 60 type = IDL_NODE_TYPE(state->tree); 61 62 if ((dispatch = state->dispatch) && (handler = dispatch[type])) 63 return handler(state); 64 return TRUE; 65 } 66 67 static int 68 msg_callback(int level, int num, int line, const char *file, 69 const char *message) 70 { 71 char *warning_message; 72 73 /* 74 * Egregious hack to permit empty files. 75 * XXX libIDL needs an API to detect this case robustly. 76 */ 77 if (0 == strcmp(message, "File empty after optimization")) { 78 parsed_empty_file = TRUE; 79 return 1; 80 } 81 82 if (!file) 83 file = "<unknown file>"; 84 warning_message = g_strdup_printf("%s:%d: %s\n", file, line, message); 85 86 fputs(warning_message, stderr); 87 g_free(warning_message); 88 return 1; 89 } 90 91 /* 92 * To keep track of the state associated with a given input file. The 'next' 93 * field lets us maintain a stack of input files. 94 */ 95 typedef struct input_data { 96 char *filename; /* where did I come from? */ 97 unsigned int lineno; /* last lineno processed */ 98 char *buf; /* contents of file */ 99 char *point; /* next char to feed to libIDL */ 100 char *max; /* 1 past last char in buf */ 101 struct input_data *next; /* file from which we were included */ 102 } input_data; 103 104 /* 105 * Passed to us by libIDL. Holds global information and the current stack of 106 * include files. 107 */ 108 typedef struct input_callback_state { 109 struct input_data *input_stack; /* linked list of input_data */ 110 GHashTable *already_included; /* to prevent redundant includes */ 111 IncludePathEntry *include_path; /* search path for included files */ 112 GSList *base_includes; /* to accumulate #includes from *first* file; 113 * for passing thru TreeState to 114 * xpidl_header backend. */ 115 } input_callback_state; 116 117 static void * 118 file_read_from_includes(const char *filename, IncludePathEntry *include_path, size_t *pcbFile) 119 { 120 IncludePathEntry *current_path = include_path; 121 char *pathname; 122 123 if (filename[0] != '/') { 124 while (current_path) { 125 pathname = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", 126 current_path->directory, filename); 127 if (!pathname) 128 return NULL; 129 void *pvFile = NULL; 130 int vrc = RTFileReadAll(pathname, &pvFile, pcbFile); 131 g_free(pathname); 132 if (RT_SUCCESS(vrc)) 133 return pvFile; 134 current_path = current_path->next; 135 } 136 } else { 137 void *pvFile = NULL; 138 int vrc = RTFileReadAll(filename, &pvFile, pcbFile); 139 if (RT_SUCCESS(vrc)) 140 return pvFile; 141 } 142 return NULL; 143 } 144 145 #if defined(XP_MAC) && defined(XPIDL_PLUGIN) 146 extern FILE* mac_fopen(const char* filename, const char *mode); 147 #endif 148 149 static input_data * 150 new_input_data(const char *filename, IncludePathEntry *include_path) 151 { 152 input_data *new_data; 153 154 /* 155 * Rather than try to keep track of many different varieties of state 156 * around the boundaries of a circular buffer, we just read in the entire 157 * file. 158 */ 159 size_t cbFile = 0; 160 void *pvFile = file_read_from_includes(filename, include_path, &cbFile); 161 if (!pvFile) 162 return NULL; 163 164 /* Need to copy the data over into a new buffer in order to be able to append a zero terminator. */ 165 char *pbBuf = (char *)RTMemDupEx(pvFile, cbFile, 1 /* for the zero terminator */); 166 if (!pbBuf) 167 { 168 RTFileReadAllFree(pvFile, cbFile); 169 return NULL; 170 } 171 172 memcpy(pbBuf, pvFile, cbFile); 173 RTFileReadAllFree(pvFile, cbFile); 174 175 new_data = xpidl_malloc(sizeof (struct input_data)); 176 if (!new_data) 177 { 178 RTMemFree(pbBuf); 179 return NULL; 180 } 181 182 new_data->point = new_data->buf = pbBuf; 183 new_data->max = pbBuf + cbFile; 184 *new_data->max = '\0'; 185 new_data->filename = xpidl_strdup(filename); 186 /* libIDL expects the line number to be that of the *next* line */ 187 new_data->lineno = 2; 188 new_data->next = NULL; 189 return new_data; 190 } 191 192 /* process pending raw section */ 193 static int 194 NextIsRaw(input_data *data, char **startp, int *lenp) 195 { 196 char *end, *start; 197 198 /* 199 * XXXmccabe still needed: an in_raw flag to handle the case where we're in 200 * a raw block, but haven't managed to copy it all to xpidl. This will 201 * happen when we have a raw block larger than 202 * IDL_input_data->fill.max_size (currently 8192.) 203 */ 204 if (!(data->point[0] == '%' && data->point[1] == '{')) 205 return 0; 206 207 start = *startp = data->point; 208 209 end = NULL; 210 while (start < data->max && (end = strstr(start, "%}"))) { 211 if (end[-1] == '\r' || 212 end[-1] == '\n') 213 break; 214 start = end + 1; 215 } 216 217 if (end && start < data->max) { 218 *lenp = end - data->point + 2; 219 return 1; 220 } else { 221 const char *filename; 222 int lineno; 223 224 IDL_file_get(&filename, &lineno); 225 msg_callback(IDL_ERROR, 0, lineno, filename, 226 "unterminated %{ block"); 227 return -1; 228 } 229 } 230 231 /* process pending comment */ 232 static int 233 NextIsComment(input_data *data, char **startp, int *lenp) 234 { 235 char *end; 236 237 if (!(data->point[0] == '/' && data->point[1] == '*')) 238 return 0; 239 240 end = strstr(data->point, "*/"); 241 *lenp = 0; 242 if (end) { 243 int skippedLines = 0; 244 char *tempPoint; 245 246 /* get current lineno */ 247 IDL_file_get(NULL,(int *)&data->lineno); 248 249 /* get line count */ 250 for (tempPoint = data->point; tempPoint < end; tempPoint++) { 251 if (*tempPoint == '\n') 252 skippedLines++; 253 } 254 255 data->lineno += skippedLines; 256 IDL_file_set(data->filename, (int)data->lineno); 257 258 *startp = end + 2; 259 260 /* If it's a ** comment, tell libIDL about it. */ 261 if (data->point[2] == '*') { 262 /* hack termination. +2 to get past '*' '/' */ 263 char t = *(end + 2); 264 *(end + 2) = '\0'; 265 IDL_queue_new_ident_comment(data->point); 266 *(end + 2) = t; 267 } 268 269 data->point = *startp; /* XXXmccabe move this out of function? */ 270 return 1; 271 } else { 272 const char *filename; 273 int lineno; 274 275 IDL_file_get(&filename, &lineno); 276 msg_callback(IDL_ERROR, 0, lineno, filename, 277 "unterminated comment"); 278 return -1; 279 } 280 } 281 282 static int 283 NextIsInclude(input_callback_state *callback_state, char **startp, 284 int *lenp) 285 { 286 input_data *data = callback_state->input_stack; 287 input_data *new_data; 288 char *filename, *end; 289 const char *scratch; 290 291 /* process the #include that we're in now */ 292 if (strncmp(data->point, "#include \"", 10)) { 293 return 0; 294 } 295 296 filename = data->point + 10; /* skip #include " */ 297 XPT_ASSERT(filename < data->max); 298 end = filename; 299 while (end < data->max) { 300 if (*end == '\"' || *end == '\n' || *end == '\r') 301 break; 302 end++; 303 } 304 305 if (*end != '\"') { 306 /* 307 * Didn't find end of include file. Scan 'til next whitespace to find 308 * some reasonable approximation of the filename, and use it to report 309 * an error. 310 */ 311 312 end = filename; 313 while (end < data->max) { 314 if (*end == ' ' || *end == '\n' || *end == '\r' || *end == '\t') 315 break; 316 end++; 317 } 318 *end = '\0'; 319 320 /* make sure we have accurate line info */ 321 IDL_file_get(&scratch, (int *)&data->lineno); 322 fprintf(stderr, 323 "%s:%u: didn't find end of quoted include name \"%s\n", 324 scratch, data->lineno, filename); 325 return -1; 326 } 327 328 *end = '\0'; 329 *startp = end + 1; 330 331 if (data->next == NULL) { 332 /* 333 * If we're in the initial file, add this filename to the list 334 * of filenames to be turned into #include "filename.h" 335 * directives in xpidl_header.c. We do it here rather than in the 336 * block below so it still gets added to the list even if it's 337 * already been recursively included from some other file. 338 */ 339 char *filename_cp = xpidl_strdup(filename); 340 341 /* note that g_slist_append accepts and likes null as list-start. */ 342 callback_state->base_includes = 343 g_slist_append(callback_state->base_includes, filename_cp); 344 } 345 346 /* store offset for when we pop, or if we skip this one */ 347 data->point = *startp; 348 349 if (!g_hash_table_lookup(callback_state->already_included, filename)) { 350 filename = xpidl_strdup(filename); 351 g_hash_table_insert(callback_state->already_included, 352 filename, (void *)TRUE); 353 new_data = new_input_data(filename, callback_state->include_path); 354 if (!new_data) { 355 char *error_message; 356 IDL_file_get(&scratch, (int *)&data->lineno); 357 error_message = 358 g_strdup_printf("can't open included file %s for reading\n", 359 filename); 360 msg_callback(IDL_ERROR, 0, 361 data->lineno, scratch, error_message); 362 g_free(error_message); 363 return -1; 364 } 365 366 new_data->next = data; 367 /* tell libIDL to exclude this IDL from the toplevel tree */ 368 IDL_inhibit_push(); 369 IDL_file_get(&scratch, (int *)&data->lineno); 370 callback_state->input_stack = new_data; 371 IDL_file_set(new_data->filename, (int)new_data->lineno); 372 } 373 374 *lenp = 0; /* this is magic, see the comment below */ 375 return 1; 376 } 377 378 static void 379 FindSpecial(input_data *data, char **startp, int *lenp) 380 { 381 char *point = data->point; 382 383 /* magic sequences are: 384 * "%{" raw block 385 * "/\*" comment 386 * "#include \"" include 387 * The first and last want a newline [\r\n] before, or the start of the 388 * file. 389 */ 390 391 #define LINE_START(data, point) (point == data->buf || \ 392 (point > data->point && \ 393 (point[-1] == '\r' || point[-1] == '\n'))) 394 395 while (point < data->max) { 396 if (point[0] == '/' && point[1] == '*') 397 break; 398 if (LINE_START(data, point)) { 399 if (point[0] == '%' && point[1] == '{') 400 break; 401 if (point[0] == '#' && !strncmp(point + 1, "include \"", 9)) 402 break; 403 } 404 point++; 405 } 406 407 #undef LINE_START 408 409 *startp = data->point; 410 *lenp = point - data->point; 411 } 412 413 #ifndef VBOX 414 /* set this with a debugger to see exactly what libIDL sees */ 415 static FILE *tracefile = NULL; 416 #endif 417 418 static int 419 input_callback(IDL_input_reason reason, union IDL_input_data *cb_data, 420 gpointer user_data) 421 { 422 input_callback_state *callback_state = user_data; 423 input_data *data = callback_state->input_stack; 424 input_data *new_data = NULL; 425 unsigned int len, copy; 426 int rv; 427 char *start; 428 429 switch(reason) { 430 case IDL_INPUT_REASON_INIT: 431 if (data == NULL || data->next == NULL) { 432 /* 433 * This is the first file being processed. As it's the target 434 * file, we only look for it in the first entry in the include 435 * path, which we assume to be the current directory. 436 */ 437 438 /* XXXmccabe proper assumption? Do we handle files in other 439 directories? */ 440 441 IncludePathEntry first_entry; 442 443 first_entry.directory = callback_state->include_path->directory; 444 first_entry.next = NULL; 445 446 new_data = new_input_data(cb_data->init.filename, 447 &first_entry); 448 } else { 449 new_data = new_input_data(cb_data->init.filename, 450 callback_state->include_path); 451 } 452 453 if (!new_data) 454 return -1; 455 456 IDL_file_set(new_data->filename, (int)new_data->lineno); 457 callback_state->input_stack = new_data; 458 return 0; 459 460 case IDL_INPUT_REASON_FILL: 461 start = NULL; 462 len = 0; 463 464 while (data->point >= data->max) { 465 if (!data->next) 466 return 0; 467 468 /* Current file is done; revert to including file */ 469 callback_state->input_stack = data->next; 470 free(data->filename); 471 RTMemFree(data->buf); 472 free(data); 473 data = callback_state->input_stack; 474 475 IDL_file_set(data->filename, (int)data->lineno); 476 IDL_inhibit_pop(); 477 } 478 479 /* 480 * Now we scan for sequences which require special attention: 481 * \n#include begins an include statement 482 * \n%{ begins a raw-source block 483 * /\* begins a comment 484 * 485 * We used to be fancier here, so make sure that we sent the most 486 * data possible at any given time. To that end, we skipped over 487 * \n%{ raw \n%} blocks and then _continued_ the search for special 488 * sequences like \n#include or /\* comments . 489 * 490 * It was really ugly, though -- liberal use of goto! lots of implicit 491 * state! what fun! -- so now we just do this: 492 * 493 * if (special at start) { 494 * process that special - 495 * - raw: send it to libIDL, and don't look inside for specials 496 * - comments: adjust point and start over 497 * - includes: push new input_data struct for included file, and 498 * start over 499 * } else { 500 * scan for next special 501 * send data up to that special to libIDL 502 * } 503 * 504 * If len is set to zero, it is a sentinel value indicating we a comment 505 * or include was found, and parsing should start over. 506 * 507 * XXX const string foo = "/\*" will just screw us horribly. 508 * Hm but. We could treat strings as we treat raw blocks, eh? 509 */ 510 511 /* 512 * Order is important, so that you can have /\* comments and 513 * #includes within raw sections, and so that you can comment out 514 * #includes. 515 */ 516 rv = NextIsRaw(data, &start, (int *)&len); 517 if (rv == -1) return -1; 518 if (!rv) { 519 /* 520 * When NextIsComment succeeds, it returns a 0 len (requesting a 521 * restart) and adjusts data->point to pick up after the comment. 522 */ 523 rv = NextIsComment(data, &start, (int *)&len); 524 if (rv == -1) return -1; 525 if (!rv) { 526 /* 527 * NextIsInclude might push a new input_data struct; if so, it 528 * will return a 0 len, letting the callback pick up the new 529 * file the next time around. 530 */ 531 rv = NextIsInclude(callback_state, &start, (int *)&len); 532 if (rv == -1) return -1; 533 if (!rv) 534 FindSpecial(data, &start, (int *)&len); 179 static int xpidlCreateLexerFromFilename(const char *pszFilename, PRTLISTANCHOR pLstIncludePaths, 180 PRTSCRIPTLEX phIdlLex) 181 { 182 char szPath[RTPATH_MAX]; 183 184 if (pszFilename[0] != '/') 185 { 186 PCXPIDLINCLUDEDIR pIt; 187 RTListForEach(pLstIncludePaths, pIt, XPIDLINCLUDEDIR, NdIncludes) 188 { 189 ssize_t cch = RTStrPrintf2(&szPath[0], sizeof(szPath), "%s%c%s", 190 pIt->pszPath, RTPATH_SLASH, pszFilename); 191 if (cch <= 0) 192 return VERR_BUFFER_OVERFLOW; 193 194 if (RTFileExists(szPath)) 195 { 196 pszFilename = szPath; 197 break; 535 198 } 536 199 } 537 538 if (len == 0) { 539 /* 540 * len == 0 is a sentinel value that means we found a comment or 541 * include. If we found a comment, point has been adjusted to 542 * point past the comment. If we found an include, a new input_data 543 * has been pushed. In both cases, calling the input_callback again 544 * will pick up the new state. 545 */ 546 return input_callback(reason, cb_data, user_data); 200 } 201 202 return RTScriptLexCreateFromFile(phIdlLex, pszFilename, NULL /*phStrCacheId*/, 203 NULL /*phStrCacheStringLit*/, NULL /*phStrCacheComments*/, 204 &g_IdlLexCfg); 205 } 206 207 208 static int xpidlParseError(PXPIDLPARSE pThis, PXPIDLINPUT pInput, PCRTSCRIPTLEXTOKEN pTok, int rc, const char *pszFmt, ...) 209 { 210 va_list Args; 211 va_start(Args, pszFmt); 212 RT_NOREF(pTok); 213 rc = RTErrInfoSetV(&pThis->ErrInfo.Core, rc, pszFmt, Args); 214 va_end(Args); 215 return rc; 216 } 217 218 219 static int xpidlLexerConsumeIfStringLit(PXPIDLPARSE pThis, PXPIDLINPUT pInput, const char **ppszStrLit) 220 { 221 PCRTSCRIPTLEXTOKEN pTok; 222 int rc = RTScriptLexQueryToken(pInput->hIdlLex, &pTok); 223 if (RT_FAILURE(rc)) 224 return xpidlParseError(pThis, pInput, pTok, rc, "Lexer: Failed to query string literal token with %Rrc", rc); 225 226 if (pTok->enmType == RTSCRIPTLEXTOKTYPE_STRINGLIT) 227 { 228 *ppszStrLit = pTok->Type.StringLit.pszString; 229 RTScriptLexConsumeToken(pInput->hIdlLex); 230 return VINF_SUCCESS; 231 } 232 233 return VINF_SUCCESS; 234 } 235 236 237 #define XPIDL_PARSE_STRING_LIT(a_pszStrLit) \ 238 const char *a_pszStrLit = NULL; \ 239 do { \ 240 int rc2 = xpidlLexerConsumeIfStringLit(pThis, pInput, &a_pszStrLit); \ 241 if (RT_FAILURE(rc2)) \ 242 return rc2; \ 243 if (!a_pszStrLit) \ 244 return xpidlParseError(pThis, pInput, NULL, VERR_INVALID_PARAMETER, "Parser: Expected a string literal"); \ 245 } while(0) 246 247 248 static PXPIDLINPUT xpidlInputCreate(const char *pszFilename, PRTLISTANCHOR pLstIncludePaths) 249 { 250 RTSCRIPTLEX hIdlLex = NULL; 251 int rc = xpidlCreateLexerFromFilename(pszFilename, pLstIncludePaths, &hIdlLex); 252 if (RT_FAILURE(rc)) 253 return NULL; 254 255 PXPIDLINPUT pInput = (PXPIDLINPUT)xpidl_malloc(sizeof (*pInput)); 256 if (!pInput) 257 { 258 RTScriptLexDestroy(hIdlLex); 259 return NULL; 260 } 261 262 RTListInit(&pInput->LstIncludes); 263 pInput->hIdlLex = hIdlLex; 264 pInput->pszFilename = xpidl_strdup(pszFilename); 265 return pInput; 266 } 267 268 269 static PXPIDLNODE xpidlNodeCreate(PXPIDLPARSE pThis, PXPIDLNODE pParent, PXPIDLINPUT pInput, XPIDLNDTYPE enmType) 270 { 271 PXPIDLNODE pNode = (PXPIDLNODE)RTMemAllocZ(sizeof(*pNode)); 272 if (pNode) 273 { 274 pNode->pParent = pParent; 275 pNode->pInput = pInput; 276 pNode->enmType = enmType; 277 } 278 else 279 xpidlParseError(pThis, pInput, NULL, VERR_NO_MEMORY, "Failed to allocate node of type %u\n", enmType); 280 281 return pNode; 282 } 283 284 285 static int xpidlParseKeyword(PXPIDLPARSE pThis, PXPIDLINPUT pInput, PRTLISTANCHOR pLstIncludePaths, 286 PCRTSCRIPTLEXTOKMATCH pKeyword) 287 { 288 RT_NOREF(pThis, pInput, pLstIncludePaths); 289 int rc; 290 switch (pKeyword->u64Val) 291 { 292 case kXpidlKeyword_Include: 293 { 294 XPIDL_PARSE_STRING_LIT(pszFilename); 295 PXPIDLINPUT pInput = xpidlInputCreate(pszFilename, pLstIncludePaths); 296 if (!pInput) 297 return xpidlParseError(pThis, pInput, NULL, VERR_INVALID_PARAMETER, "Failed opening include file '%s'", 298 pszFilename); 299 300 RTListAppend(&pThis->LstInputs, &pInput->NdInput); 301 rc = xpidlParseIdl(pThis, pInput, pLstIncludePaths); 302 break; 547 303 } 548 549 copy = MIN(len, (unsigned int) cb_data->fill.max_size); 550 memcpy(cb_data->fill.buffer, start, copy); 551 data->point = start + copy; 552 553 #ifndef VBOX 554 if (tracefile) 555 fwrite(cb_data->fill.buffer, copy, 1, tracefile); 556 #endif 557 558 return copy; 559 560 case IDL_INPUT_REASON_ABORT: 561 case IDL_INPUT_REASON_FINISH: 562 while (data != NULL) { 563 input_data *next; 564 565 next = data->next; 566 free(data->filename); 567 RTMemFree(data->buf); 568 free(data); 569 data = next; 304 case kXpidlKeyword_Typedef: 305 { 306 /** @todo */ 307 break; 308 } 309 default: 310 rc = xpidlParseError(pThis, pInput, NULL, VERR_INVALID_PARAMETER, "Unexpected keyword '%s' found", 311 pKeyword->pszMatch); 312 } 313 return rc; 314 } 315 316 317 static int xpidlParseAttributes(PXPIDLPARSE pThis, PXPIDLINPUT pInput) 318 { 319 RT_NOREF(pThis, pInput); 320 return VERR_NOT_IMPLEMENTED; 321 } 322 323 324 static int xpidlParseIdl(PXPIDLPARSE pThis, PXPIDLINPUT pInput, PRTLISTANCHOR pLstIncludePaths) 325 { 326 /* Parse IDL file. */ 327 int rc; 328 for (;;) 329 { 330 PCRTSCRIPTLEXTOKEN pTok; 331 rc = RTScriptLexQueryToken(pInput->hIdlLex, &pTok); 332 if (RT_FAILURE(rc)) 333 return xpidlParseError(pThis, pInput, NULL, rc, "Parser: Failed to query next token with %Rrc", rc); 334 335 if (pTok->enmType == RTSCRIPTLEXTOKTYPE_EOS) 336 break; 337 338 /* 339 * In this outer loop we can either get comments, keywords or [] for 340 * attributes of following nodes. 341 */ 342 switch (pTok->enmType) 343 { 344 case RTSCRIPTLEXTOKTYPE_COMMENT_SINGLE_LINE: 345 RTScriptLexConsumeToken(pInput->hIdlLex); /* These get ignored entirely. */ 346 break; 347 case RTSCRIPTLEXTOKTYPE_COMMENT_MULTI_LINE: 348 { 349 /* Could be a raw block, check that the string starts with %{C++. */ 350 if (!strncmp(pTok->Type.Comment.pszComment, RT_STR_TUPLE("%{C++"))) 351 { 352 /* Create a new raw block node. */ 353 PXPIDLNODE pNode = xpidlNodeCreate(pThis, NULL, pInput, kXpidlNdType_RawBlock); 354 if (pNode) 355 { 356 pNode->u.RawBlock.pszRaw = pTok->Type.Comment.pszComment + 5; 357 pNode->u.RawBlock.cchRaw = pTok->Type.Comment.cchComment - (5 + 2 + 1); /* Start + end + zero terminator. */ 358 RTListAppend(&pThis->LstNodes, &pNode->NdLst); 359 } 360 else 361 rc = VERR_NO_MEMORY; 362 } 363 /* else: Regular multi line comment, gets ignored. */ 364 RTScriptLexConsumeToken(pInput->hIdlLex); 365 break; 366 } 367 case RTSCRIPTLEXTOKTYPE_KEYWORD: 368 { 369 PCRTSCRIPTLEXTOKMATCH pKeyword = pTok->Type.Keyword.pKeyword; 370 RTScriptLexConsumeToken(pInput->hIdlLex); 371 rc = xpidlParseKeyword(pThis, pInput, pLstIncludePaths, pKeyword); /** @todo This allows too much */ 372 break; 373 } 374 case RTSCRIPTLEXTOKTYPE_PUNCTUATOR: 375 { 376 if (pTok->Type.Punctuator.pPunctuator->u64Val == '[') 377 { 378 RTScriptLexConsumeToken(pInput->hIdlLex); 379 rc = xpidlParseAttributes(pThis, pInput); 380 } 381 else 382 rc = xpidlParseError(pThis, pInput, pTok, VERR_INVALID_PARAMETER, "Unexpected punctuator found, expected '[', got '%c'", 383 (char)pTok->Type.Punctuator.pPunctuator->u64Val); 384 break; 385 } 386 case RTSCRIPTLEXTOKTYPE_ERROR: 387 rc = xpidlParseError(pThis, pInput, pTok, VERR_INTERNAL_ERROR, "Internal lexer error: %s", pTok->Type.Error.pErr->pszMsg); 388 break; 389 default: 390 rc = xpidlParseError(pThis, pInput, pTok, VERR_INVALID_PARAMETER, "Unexpected keyword found, expected raw block, keyword or '['"); 391 break; 570 392 } 571 callback_state->input_stack = NULL; 572 return 0; 573 574 default: 575 g_error("unknown input reason %d!", reason); 576 return -1; 577 } 578 } 579 580 static void 581 free_ghash_key(gpointer key, gpointer value, gpointer user_data) 582 { 583 /* We're only storing TRUE in the value... */ 584 free(key); 585 } 586 587 static void 588 free_gslist_data(gpointer data, gpointer user_data) 589 { 590 free(data); 591 } 592 593 /* Pick up unlink. */ 594 #include <unistd.h> 595 596 int 597 xpidl_process_idl(char *filename, IncludePathEntry *include_path, 598 char *file_basename, ModeData *mode) 599 { 600 char *tmp, *outname, *real_outname = NULL; 601 IDL_tree top; 602 TreeState state; 603 int rv; 604 input_callback_state callback_state; 605 gboolean ok = TRUE; 606 backend *emitter; 607 608 callback_state.input_stack = NULL; 609 callback_state.base_includes = NULL; 610 callback_state.include_path = include_path; 611 callback_state.already_included = g_hash_table_new(g_str_hash, g_str_equal); 612 613 if (!callback_state.already_included) { 614 fprintf(stderr, "failed to create hashtable. out of memory?\n"); 615 return 0; 616 } 617 618 state.basename = xpidl_strdup(filename); 619 620 /* if basename has an .extension, truncate it. */ 621 tmp = strrchr(state.basename, '.'); 622 if (tmp) 623 *tmp = '\0'; 624 625 if (!file_basename) 626 outname = xpidl_strdup(state.basename); 393 394 if (RT_FAILURE(rc)) 395 break; 396 } 397 398 return rc; 399 } 400 401 402 int xpidl_process_idl(char *filename, PRTLISTANCHOR pLstIncludePaths, 403 char *file_basename, ModeData *mode) 404 { 405 XPIDLPARSE ParseState; 406 RTListInit(&ParseState.LstInputs); 407 RTListInit(&ParseState.LstNodes); 408 RTErrInfoInitStatic(&ParseState.ErrInfo); 409 410 PXPIDLINPUT pInput = xpidlInputCreate(filename, pLstIncludePaths); 411 if (!pInput) 412 return VERR_NO_MEMORY; 413 414 RTListAppend(&ParseState.LstInputs, &pInput->NdInput); 415 int rc = xpidlParseIdl(&ParseState, pInput, pLstIncludePaths); 416 if (RT_SUCCESS(rc)) 417 { 418 /** @todo Output. */ 419 } 627 420 else 628 outname = xpidl_strdup(file_basename); 629 630 /* so we don't include it again! */ 631 g_hash_table_insert(callback_state.already_included, 632 xpidl_strdup(filename), (void *)TRUE); 633 634 parsed_empty_file = FALSE; 635 636 rv = IDL_parse_filename_with_input(filename, input_callback, &callback_state, 637 msg_callback, &top, 638 &state.ns, 639 IDLF_IGNORE_FORWARDS | 640 IDLF_XPIDL, 641 enable_warnings ? IDL_WARNING1 : 642 IDL_ERROR); 643 if (parsed_empty_file) { 644 /* 645 * If we've detected (via hack in msg_callback) that libIDL returned 646 * failure because it found a file with no IDL, set the parse tree to 647 * null and proceed. Allowing this is useful to permit .idl files that 648 * collect #includes. 649 */ 650 top = NULL; 651 state.ns = NULL; 652 } else if (rv != IDL_SUCCESS) { 653 if (rv == -1) { 654 g_warning("Parse of %s failed: %s", filename, g_strerror(errno)); 655 } else { 656 g_warning("Parse of %s failed", filename); 657 } 658 free(outname); 659 return 0; 660 } 661 662 state.basename = xpidl_strdup(filename); 663 tmp = strrchr(state.basename, '.'); 664 if (tmp) 665 *tmp = '\0'; 666 667 /* so xpidl_header.c can use it to generate a list of #include directives */ 668 state.base_includes = callback_state.base_includes; 669 670 emitter = mode->factory(); 671 state.dispatch = emitter->dispatch_table; 672 673 if (strcmp(outname, "-")) { 674 const char *fopen_mode; 675 char *out_basename; 676 677 /* explicit_output_filename can't be true without a filename */ 678 if (explicit_output_filename) { 679 real_outname = g_strdup(outname); 680 } else { 681 682 if (!file_basename) { 683 out_basename = xpidl_basename(outname); 684 } else { 685 out_basename = outname; 686 } 687 688 real_outname = g_strdup_printf("%s.%s", out_basename, mode->suffix); 689 if (out_basename != outname) 690 g_free(out_basename); 691 } 692 693 /* Use binary write for typelib mode */ 694 fopen_mode = (strcmp(mode->mode, "typelib")) ? "w" : "wb"; 695 state.file = fopen(real_outname, fopen_mode); 696 if (!state.file) { 697 perror("error opening output file"); 698 free(outname); 699 return 0; 700 } 701 } else { 702 state.file = stdout; 703 } 704 state.tree = top; 705 706 if (emitter->emit_prolog) 707 emitter->emit_prolog(&state); 708 if (state.tree) /* Only if we have a tree to process. */ 709 ok = xpidl_process_node(&state); 710 if (emitter->emit_epilog) 711 emitter->emit_epilog(&state); 712 713 if (state.file != stdout) 714 fclose(state.file); 715 free(state.basename); 716 free(outname); 717 g_hash_table_foreach(callback_state.already_included, free_ghash_key, NULL); 718 g_hash_table_destroy(callback_state.already_included); 719 g_slist_foreach(callback_state.base_includes, free_gslist_data, NULL); 720 721 if (state.ns) 722 IDL_ns_free(state.ns); 723 if (top) 724 IDL_tree_free(top); 725 726 if (real_outname != NULL) { 727 /* 728 * Delete partial output file on failure. (Mac does this in the plugin 729 * driver code, if the compiler returns failure.) 730 */ 731 if (!ok) 732 unlink(real_outname); 733 734 g_free(real_outname); 735 } 736 737 return ok; 738 } 421 RTMsgError(ParseState.ErrInfo.Core.pszMsg); 422 423 return rc; 424 } -
trunk/src/libs/xpcom18a4/xpcom/typelib/xpidl-new/xpidl_util.c
r103505 r108284 73 73 } 74 74 75 #if 0 75 76 void 76 77 xpidl_write_comment(TreeState *state, int indent) … … 83 84 fputs(" */\n", state->file); 84 85 } 86 #endif 85 87 86 88 /* … … 88 90 * UUID_LENGTH bytes. 89 91 */ 90 gboolean 92 bool 91 93 xpidl_sprint_iid(nsID *id, char iidbuf[]) 92 94 { … … 116 118 * so we re-implement nsID::Parse here. 117 119 */ 118 gboolean 120 bool 119 121 xpidl_parse_iid(nsID *id, const char *str) 120 122 { … … 126 128 127 129 if (strlen(str) != 36) { 128 return FALSE;130 return false; 129 131 } 130 132 … … 152 154 } 153 155 #endif 154 return (gboolean)(count == 11); 155 } 156 156 return (count == 11); 157 } 158 159 #if 0 157 160 gboolean 158 161 verify_const_declaration(IDL_tree const_tree) { … … 847 850 return result; 848 851 } 852 #endif
Note:
See TracChangeset
for help on using the changeset viewer.