Chromium Code Reviews| 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 = library_url_chars; | |
| 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 for (int idx = 0; idx < url_mapping->count(); idx++) { | |
| 117 const char* url_name = url_mapping->GetArgument(idx); | |
| 118 int len = strlen(library_url_chars); | |
|
Anton Muhin
2011/11/14 14:02:14
hoist len out of for loop?
siva
2011/11/14 22:17:09
Done.
| |
| 119 if (!strncmp(library_url_chars, url_name, len) && | |
| 120 (url_name[len] == ',')) { | |
|
Anton Muhin
2011/11/14 14:02:14
should we protect from that? if yes, we may need
siva
2011/11/14 22:17:09
Not sure I understand what we should protect again
| |
| 121 const char* url_mapped_name = url_name + len + 1; | |
| 122 if (strlen(url_mapped_name) != 0) { | |
|
Anton Muhin
2011/11/14 14:02:14
ditto.
siva
2011/11/14 22:17:09
Ditto.
On 2011/11/14 14:02:14, antonmuhin wrote:
| |
| 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, | |
|
Anton Muhin
2011/11/14 14:02:14
doesn't we have pretty similar code in process_scr
siva
2011/11/14 22:17:09
I have refactored this to avoid the duplication.
| |
| 134 const char* url_chars) { | |
| 135 // Create the full path based on the including library and the url. | |
| 136 | |
| 137 // Calculate the path. | |
| 138 | |
| 139 if (File::IsAbsolutePath(url_chars)) { | |
| 140 return Dart_NewString(url_chars); | |
| 141 } | |
| 142 char* path = strdup(library_url_chars); | |
| 143 if (path == NULL) { | |
| 144 return Dart_Error("Unable to duplicate string : possibly out of memory"); | |
| 145 } | |
| 146 char* path_sep = strrchr(path, File::PathSeparator()[0]); | |
| 147 if (path_sep == NULL) { | |
| 148 // No separator found: Reference is a file in local directory. | |
| 149 free(path); | |
| 150 return Dart_NewString(url_chars); | |
| 151 } | |
| 152 *path_sep = '\0'; | |
| 153 intptr_t len = snprintf(NULL, 0, "%s%s%s", | |
| 154 path, File::PathSeparator(), url_chars); | |
| 155 char* absolute_filename = reinterpret_cast<char*>(malloc(len + 1)); | |
| 156 ASSERT(absolute_filename != NULL); | |
| 157 snprintf(absolute_filename, len + 1, "%s%s%s", | |
| 158 path, File::PathSeparator(), url_chars); | |
| 159 free(path); | |
| 160 char* canonical_filename = File::GetCanonicalPath(absolute_filename); | |
| 161 if (canonical_filename == NULL) { | |
| 162 return Dart_NewString(absolute_filename); | |
| 163 } | |
| 164 free(absolute_filename); | |
| 165 Dart_Handle canon_url = Dart_NewString(canonical_filename); | |
| 166 free(const_cast<char*>(canonical_filename)); | |
| 167 return canon_url; | |
| 168 } | |
| 169 | |
| 170 | |
| 171 static Dart_Handle CreateSnapshotLibraryTagHandler(Dart_LibraryTag tag, | |
| 172 Dart_Handle library, | |
| 173 Dart_Handle url) { | |
| 174 if (!Dart_IsLibrary(library)) { | |
| 175 return Dart_Error("not a library"); | |
| 176 } | |
| 177 if (!Dart_IsString8(url)) { | |
| 178 return Dart_Error("url is not a string"); | |
| 179 } | |
| 180 const char* url_chars = NULL; | |
| 181 Dart_Handle result = Dart_StringToCString(url, &url_chars); | |
| 182 if (Dart_IsError(result)) { | |
| 183 return Dart_Error("accessing url characters failed"); | |
| 184 } | |
| 185 | |
| 186 // If the URL starts with "dart:" then it is handled specially. | |
| 187 static const char* kDartScheme = "dart:"; | |
| 188 static const intptr_t kDartSchemeLen = strlen(kDartScheme); | |
| 189 if (strncmp(url_chars, kDartScheme, kDartSchemeLen) == 0) { | |
| 190 if (tag == kCanonicalizeUrl) { | |
| 191 return Dart_NewString(url_chars); | |
| 192 } | |
| 193 url_chars = MapLibraryUrl(url_chars); | |
|
Anton Muhin
2011/11/14 14:02:14
If I import mapped lib in mapped lib, won't we hav
Anton Muhin
2011/11/14 16:44:05
Sorry, I now think you handle this case correctly
siva
2011/11/14 22:17:09
Yes the canonicalization part just returns the URL
| |
| 194 } | |
| 195 // Get the url of the calling library. | |
| 196 Dart_Handle library_url = Dart_LibraryUrl(library); | |
| 197 if (Dart_IsError(library_url)) { | |
| 198 return Dart_Error("accessing library url failed"); | |
| 199 } | |
| 200 if (!Dart_IsString8(library_url)) { | |
| 201 return Dart_Error("library url is not a string"); | |
| 202 } | |
| 203 const char* library_url_chars = NULL; | |
| 204 result = Dart_StringToCString(library_url, &library_url_chars); | |
| 205 if (Dart_IsError(result)) { | |
| 206 return Dart_Error("accessing library url characters failed"); | |
| 207 } | |
| 208 library_url_chars = MapLibraryUrl(library_url_chars); | |
| 209 Dart_Handle canon_url = CanonicalizeUrl(library_url_chars, url_chars); | |
| 210 if (Dart_IsError(canon_url)) { | |
| 211 return canon_url; // canon_url contains the error string. | |
| 212 } | |
| 213 if (tag == kCanonicalizeUrl) { | |
| 214 return canon_url; | |
| 215 } | |
| 216 result = Dart_StringToCString(canon_url, &url_chars); | |
| 217 if (Dart_IsError(result)) { | |
| 218 return Dart_Error("accessing canon url characters failed"); | |
| 219 } | |
| 220 // The tag is either an import or a source tag. Read the file based on the | |
| 221 // url chars. | |
| 222 Dart_Handle source = ReadStringFromFile(url_chars); | |
| 223 if (Dart_IsError(source)) { | |
| 224 return source; // source contains the error string. | |
| 225 } | |
| 226 if (tag == kImportTag) { | |
| 227 return Dart_LoadLibrary(url, source); | |
| 228 } else if (tag == kSourceTag) { | |
| 229 return Dart_LoadSource(library, url, source); | |
| 230 } | |
| 231 return Dart_Error("wrong tag"); | |
| 232 } | |
| 233 | |
| 234 | |
| 235 static Dart_Handle LoadSnapshotCreationScript(const char* script_name) { | |
| 236 Dart_Handle source = ReadStringFromFile(script_name); | |
| 237 if (Dart_IsError(source)) { | |
| 238 return source; // source contains the error string. | |
| 239 } | |
| 240 Dart_Handle url = Dart_NewString(script_name); | |
| 241 | |
| 242 return Dart_LoadScript(url, source, CreateSnapshotLibraryTagHandler); | |
| 243 } | |
| 244 | |
| 245 | |
| 93 static void* SnapshotCreateCallback(void* data) { | 246 static void* SnapshotCreateCallback(void* data) { |
| 94 const char* script_name = reinterpret_cast<const char*>(data); | 247 const char* script_name = reinterpret_cast<const char*>(data); |
| 95 Dart_Handle result; | 248 Dart_Handle result; |
| 96 Dart_EnterScope(); | 249 Dart_EnterScope(); |
| 97 | 250 |
| 98 ASSERT(snapshot_filename != NULL); | 251 ASSERT(snapshot_filename != NULL); |
| 99 | 252 |
| 100 // If a file is specified on the command line, load it up before a snapshot | 253 // If a file is specified on the command line, load it up before a snapshot |
| 101 // is created. | 254 // is created. |
| 102 if (script_name != NULL) { | 255 if (script_name != NULL) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 fprintf(stderr, | 297 fprintf(stderr, |
| 145 "dart [<vm-flags>] " | 298 "dart [<vm-flags>] " |
| 146 "[<dart-script-file>]\n"); | 299 "[<dart-script-file>]\n"); |
| 147 } | 300 } |
| 148 | 301 |
| 149 | 302 |
| 150 int main(int argc, char** argv) { | 303 int main(int argc, char** argv) { |
| 151 CommandLineOptions vm_options(argc); | 304 CommandLineOptions vm_options(argc); |
| 152 char* script_name; | 305 char* script_name; |
| 153 | 306 |
| 307 // Initialize the URL mapping array. | |
| 308 CommandLineOptions url_mapping_array(argc); | |
| 309 url_mapping = &url_mapping_array; | |
| 310 | |
| 154 // Parse command line arguments. | 311 // Parse command line arguments. |
| 155 if (ParseArguments(argc, | 312 if (ParseArguments(argc, |
| 156 argv, | 313 argv, |
| 157 &vm_options, | 314 &vm_options, |
| 158 &script_name) < 0) { | 315 &script_name) < 0) { |
| 159 PrintUsage(); | 316 PrintUsage(); |
| 160 return 255; | 317 return 255; |
| 161 } | 318 } |
| 162 | 319 |
| 163 if (snapshot_filename == NULL) { | 320 if (snapshot_filename == NULL) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 175 // and writes out a snapshot. | 332 // and writes out a snapshot. |
| 176 Dart_Isolate isolate = Dart_CreateIsolate(NULL, script_name); | 333 Dart_Isolate isolate = Dart_CreateIsolate(NULL, script_name); |
| 177 if (isolate == NULL) { | 334 if (isolate == NULL) { |
| 178 return 255; | 335 return 255; |
| 179 } | 336 } |
| 180 | 337 |
| 181 // Shutdown the isolate. | 338 // Shutdown the isolate. |
| 182 Dart_ShutdownIsolate(); | 339 Dart_ShutdownIsolate(); |
| 183 return 0; | 340 return 0; |
| 184 } | 341 } |
| OLD | NEW |