| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Generate a snapshot file after loading all the scripts specified on the | 5 // Generate a snapshot file after loading all the scripts specified on the |
| 6 // command line. | 6 // command line. |
| 7 | 7 |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| 11 | 11 |
| 12 #include "include/dart_api.h" | 12 #include "include/dart_api.h" |
| 13 | 13 |
| 14 #include "bin/builtin.h" | 14 #include "bin/builtin.h" |
| 15 #include "bin/file.h" | 15 #include "bin/file.h" |
| 16 #include "bin/globals.h" | 16 #include "bin/globals.h" |
| 17 #include "bin/process_script.h" | 17 #include "bin/process_script.h" |
| 18 | 18 |
| 19 // Global state that indicates whether a snapshot is to be created and | 19 // Global state that indicates whether a snapshot is to be created and |
| 20 // if so which file to write the snapshot into. | 20 // if so which file to write the snapshot into. |
| 21 static const char* snapshot_filename = NULL; | 21 static const char* snapshot_filename = NULL; |
| 22 | 22 |
| 23 // Global state that captures the URL mappings specified on the command line. |
| 24 static CommandLineOptions* url_mapping = NULL; |
| 25 |
| 23 static bool IsValidFlag(const char* name, | 26 static bool IsValidFlag(const char* name, |
| 24 const char* prefix, | 27 const char* prefix, |
| 25 intptr_t prefix_length) { | 28 intptr_t prefix_length) { |
| 26 intptr_t name_length = strlen(name); | 29 intptr_t name_length = strlen(name); |
| 27 return ((name_length > prefix_length) && | 30 return ((name_length > prefix_length) && |
| 28 (strncmp(name, prefix, prefix_length) == 0)); | 31 (strncmp(name, prefix, prefix_length) == 0)); |
| 29 } | 32 } |
| 30 | 33 |
| 31 | 34 |
| 32 static const char* ProcessOption(const char* option, const char* name) { | 35 static const char* ProcessOption(const char* option, const char* name) { |
| 33 const intptr_t length = strlen(name); | 36 const intptr_t length = strlen(name); |
| 34 if (strncmp(option, name, length) == 0) { | 37 if (strncmp(option, name, length) == 0) { |
| 35 return (option + length); | 38 return (option + length); |
| 36 } | 39 } |
| 37 return NULL; | 40 return NULL; |
| 38 } | 41 } |
| 39 | 42 |
| 40 | 43 |
| 41 static bool ProcessSnapshotOption(const char* option) { | 44 static bool ProcessSnapshotOption(const char* option) { |
| 42 const char* kSnapshotOption = "--snapshot="; | 45 const char* kSnapshotOption = "--snapshot="; |
| 43 snapshot_filename = ProcessOption(option, kSnapshotOption); | 46 const char* name = ProcessOption(option, kSnapshotOption); |
| 44 return snapshot_filename != NULL; | 47 if (name != NULL) { |
| 48 snapshot_filename = name; |
| 49 return true; |
| 50 } |
| 51 return false; |
| 52 } |
| 53 |
| 54 |
| 55 static bool ProcessURLmappingOption(const char* option) { |
| 56 const char* kURLmappingOption = "--url_mapping="; |
| 57 const char* mapping = ProcessOption(option, kURLmappingOption); |
| 58 if (mapping != NULL) { |
| 59 url_mapping->AddArgument(mapping); |
| 60 return true; |
| 61 } |
| 62 return false; |
| 45 } | 63 } |
| 46 | 64 |
| 47 | 65 |
| 48 // Parse out the command line arguments. Returns -1 if the arguments | 66 // Parse out the command line arguments. Returns -1 if the arguments |
| 49 // are incorrect, 0 otherwise. | 67 // are incorrect, 0 otherwise. |
| 50 static int ParseArguments(int argc, | 68 static int ParseArguments(int argc, |
| 51 char** argv, | 69 char** argv, |
| 52 CommandLineOptions* vm_options, | 70 CommandLineOptions* vm_options, |
| 53 char** script_name) { | 71 char** script_name) { |
| 54 const char* kPrefix = "--"; | 72 const char* kPrefix = "--"; |
| 55 const intptr_t kPrefixLen = strlen(kPrefix); | 73 const intptr_t kPrefixLen = strlen(kPrefix); |
| 56 | 74 |
| 57 // Skip the binary name. | 75 // Skip the binary name. |
| 58 int i = 1; | 76 int i = 1; |
| 59 | 77 |
| 60 // Parse out the vm options. | 78 // Parse out the vm options. |
| 61 while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) { | 79 while ((i < argc) && IsValidFlag(argv[i], kPrefix, kPrefixLen)) { |
| 62 if (ProcessSnapshotOption(argv[i])) { | 80 if (ProcessSnapshotOption(argv[i]) || ProcessURLmappingOption(argv[i])) { |
| 63 i += 1; | 81 i += 1; |
| 64 continue; | 82 continue; |
| 65 } | 83 } |
| 66 vm_options->AddArgument(argv[i]); | 84 vm_options->AddArgument(argv[i]); |
| 67 i += 1; | 85 i += 1; |
| 68 } | 86 } |
| 69 | 87 |
| 70 // Get the script name. | 88 // Get the script name. |
| 71 if (i < argc) { | 89 if (i < argc) { |
| 72 *script_name = argv[i]; | 90 *script_name = argv[i]; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 83 const bool kWritable = true; | 101 const bool kWritable = true; |
| 84 File* file = File::Open(snapshot_filename, kWritable); | 102 File* file = File::Open(snapshot_filename, kWritable); |
| 85 ASSERT(file != NULL); | 103 ASSERT(file != NULL); |
| 86 for (intptr_t i = 0; i < size; i++) { | 104 for (intptr_t i = 0; i < size; i++) { |
| 87 file->WriteByte(buffer[i]); | 105 file->WriteByte(buffer[i]); |
| 88 } | 106 } |
| 89 delete file; | 107 delete file; |
| 90 } | 108 } |
| 91 | 109 |
| 92 | 110 |
| 111 static const char* MapLibraryUrl(const char* library_url_chars) { |
| 112 const char* mapped_url_chars = NULL; |
| 113 if (url_mapping != NULL) { |
| 114 // We need to check if the passed in url is found in the url_mapping array, |
| 115 // in that case use the mapped entry. |
| 116 int len = strlen(library_url_chars); |
| 117 for (int idx = 0; idx < url_mapping->count(); idx++) { |
| 118 const char* url_name = url_mapping->GetArgument(idx); |
| 119 if (!strncmp(library_url_chars, url_name, len) && |
| 120 (url_name[len] == ',')) { |
| 121 const char* url_mapped_name = url_name + len + 1; |
| 122 if (strlen(url_mapped_name) != 0) { |
| 123 mapped_url_chars = url_mapped_name; |
| 124 } |
| 125 break; |
| 126 } |
| 127 } |
| 128 } |
| 129 return mapped_url_chars; |
| 130 } |
| 131 |
| 132 |
| 133 static Dart_Handle CanonicalizeUrl(const char* library_url_chars, |
| 134 const char* url_chars) { |
| 135 // Calculate the canonical path based on the importing library and the url. |
| 136 const char* canonical_filename = GetCanonicalPath(library_url_chars, |
| 137 url_chars); |
| 138 Dart_Handle canon_url = Dart_NewString(canonical_filename); |
| 139 free(const_cast<char*>(canonical_filename)); |
| 140 return canon_url; |
| 141 } |
| 142 |
| 143 |
| 144 static Dart_Handle CreateSnapshotLibraryTagHandler(Dart_LibraryTag tag, |
| 145 Dart_Handle library, |
| 146 Dart_Handle url) { |
| 147 if (!Dart_IsLibrary(library)) { |
| 148 return Dart_Error("not a library"); |
| 149 } |
| 150 if (!Dart_IsString8(url)) { |
| 151 return Dart_Error("url is not a string"); |
| 152 } |
| 153 const char* url_chars = NULL; |
| 154 Dart_Handle result = Dart_StringToCString(url, &url_chars); |
| 155 if (Dart_IsError(result)) { |
| 156 return Dart_Error("accessing url characters failed"); |
| 157 } |
| 158 |
| 159 // If the URL starts with "dart:" then it is handled specially. |
| 160 static const char* kDartScheme = "dart:"; |
| 161 static const intptr_t kDartSchemeLen = strlen(kDartScheme); |
| 162 if (strncmp(url_chars, kDartScheme, kDartSchemeLen) == 0) { |
| 163 if (tag == kCanonicalizeUrl) { |
| 164 return Dart_NewString(url_chars); |
| 165 } |
| 166 const char* mapped_url_chars = MapLibraryUrl(url_chars); |
| 167 if (mapped_url_chars != NULL) { |
| 168 // We have a URL mapping specified, just return the mapped version. |
| 169 return Dart_NewString(mapped_url_chars); |
| 170 } |
| 171 } |
| 172 // Get the url of the calling library. |
| 173 Dart_Handle library_url = Dart_LibraryUrl(library); |
| 174 if (Dart_IsError(library_url)) { |
| 175 return Dart_Error("accessing library url failed"); |
| 176 } |
| 177 if (!Dart_IsString8(library_url)) { |
| 178 return Dart_Error("library url is not a string"); |
| 179 } |
| 180 const char* library_url_chars = NULL; |
| 181 result = Dart_StringToCString(library_url, &library_url_chars); |
| 182 if (Dart_IsError(result)) { |
| 183 return Dart_Error("accessing library url characters failed"); |
| 184 } |
| 185 library_url_chars = MapLibraryUrl(library_url_chars); |
| 186 Dart_Handle canon_url = CanonicalizeUrl(library_url_chars, url_chars); |
| 187 if (Dart_IsError(canon_url)) { |
| 188 return canon_url; // canon_url contains the error string. |
| 189 } |
| 190 if (tag == kCanonicalizeUrl) { |
| 191 return canon_url; |
| 192 } |
| 193 result = Dart_StringToCString(canon_url, &url_chars); |
| 194 if (Dart_IsError(result)) { |
| 195 return Dart_Error("accessing canon url characters failed"); |
| 196 } |
| 197 // The tag is either an import or a source tag. Read the file based on the |
| 198 // url chars. |
| 199 Dart_Handle source = ReadStringFromFile(url_chars); |
| 200 if (Dart_IsError(source)) { |
| 201 return source; // source contains the error string. |
| 202 } |
| 203 if (tag == kImportTag) { |
| 204 return Dart_LoadLibrary(url, source); |
| 205 } else if (tag == kSourceTag) { |
| 206 return Dart_LoadSource(library, url, source); |
| 207 } |
| 208 return Dart_Error("wrong tag"); |
| 209 } |
| 210 |
| 211 |
| 212 static Dart_Handle LoadSnapshotCreationScript(const char* script_name) { |
| 213 Dart_Handle source = ReadStringFromFile(script_name); |
| 214 if (Dart_IsError(source)) { |
| 215 return source; // source contains the error string. |
| 216 } |
| 217 Dart_Handle url = Dart_NewString(script_name); |
| 218 |
| 219 return Dart_LoadScript(url, source, CreateSnapshotLibraryTagHandler); |
| 220 } |
| 221 |
| 222 |
| 93 static void* SnapshotCreateCallback(void* data) { | 223 static void* SnapshotCreateCallback(void* data) { |
| 94 const char* script_name = reinterpret_cast<const char*>(data); | 224 const char* script_name = reinterpret_cast<const char*>(data); |
| 95 Dart_Handle result; | 225 Dart_Handle result; |
| 96 Dart_EnterScope(); | 226 Dart_EnterScope(); |
| 97 | 227 |
| 98 ASSERT(snapshot_filename != NULL); | 228 ASSERT(snapshot_filename != NULL); |
| 99 | 229 |
| 100 // If a file is specified on the command line, load it up before a snapshot | 230 // If a file is specified on the command line, load it up before a snapshot |
| 101 // is created. | 231 // is created. |
| 102 if (script_name != NULL) { | 232 if (script_name != NULL) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 fprintf(stderr, | 274 fprintf(stderr, |
| 145 "dart [<vm-flags>] " | 275 "dart [<vm-flags>] " |
| 146 "[<dart-script-file>]\n"); | 276 "[<dart-script-file>]\n"); |
| 147 } | 277 } |
| 148 | 278 |
| 149 | 279 |
| 150 int main(int argc, char** argv) { | 280 int main(int argc, char** argv) { |
| 151 CommandLineOptions vm_options(argc); | 281 CommandLineOptions vm_options(argc); |
| 152 char* script_name; | 282 char* script_name; |
| 153 | 283 |
| 284 // Initialize the URL mapping array. |
| 285 CommandLineOptions url_mapping_array(argc); |
| 286 url_mapping = &url_mapping_array; |
| 287 |
| 154 // Parse command line arguments. | 288 // Parse command line arguments. |
| 155 if (ParseArguments(argc, | 289 if (ParseArguments(argc, |
| 156 argv, | 290 argv, |
| 157 &vm_options, | 291 &vm_options, |
| 158 &script_name) < 0) { | 292 &script_name) < 0) { |
| 159 PrintUsage(); | 293 PrintUsage(); |
| 160 return 255; | 294 return 255; |
| 161 } | 295 } |
| 162 | 296 |
| 163 if (snapshot_filename == NULL) { | 297 if (snapshot_filename == NULL) { |
| 164 fprintf(stderr, "No snapshot output file specified\n"); | 298 fprintf(stderr, "No snapshot output file specified\n"); |
| 165 return 255; | 299 return 255; |
| 166 } | 300 } |
| 167 | 301 |
| 168 // Initialize the Dart VM. | 302 // Initialize the Dart VM (TODO(asiva) - remove const_cast once |
| 303 // dart API is fixed to take a const char** in Dart_Initialize). |
| 169 Dart_Initialize(vm_options.count(), | 304 Dart_Initialize(vm_options.count(), |
| 170 vm_options.arguments(), | 305 const_cast<char**>(vm_options.arguments()), |
| 171 SnapshotCreateCallback); | 306 SnapshotCreateCallback); |
| 172 | 307 |
| 173 // Create an isolate. As a side effect, SnapshotCreateCallback | 308 // Create an isolate. As a side effect, SnapshotCreateCallback |
| 174 // gets called, which loads the script (if one is specified), its libraries | 309 // gets called, which loads the script (if one is specified), its libraries |
| 175 // and writes out a snapshot. | 310 // and writes out a snapshot. |
| 176 Dart_Isolate isolate = Dart_CreateIsolate(NULL, script_name); | 311 Dart_Isolate isolate = Dart_CreateIsolate(NULL, script_name); |
| 177 if (isolate == NULL) { | 312 if (isolate == NULL) { |
| 178 return 255; | 313 return 255; |
| 179 } | 314 } |
| 180 | 315 |
| 181 // Shutdown the isolate. | 316 // Shutdown the isolate. |
| 182 Dart_ShutdownIsolate(); | 317 Dart_ShutdownIsolate(); |
| 183 return 0; | 318 return 0; |
| 184 } | 319 } |
| OLD | NEW |