1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
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
15 * The Original Code is mozilla.org code.
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.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * JavaScript Debugging support - Source Text functions
46 void JSD_ASSERT_VALID_SOURCE_TEXT(JSDSourceText
* jsdsrc
)
49 JS_ASSERT(jsdsrc
->url
);
53 /***************************************************************************/
54 /* XXX add notification */
57 _clearText(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
62 jsdsrc
->textLength
= 0;
63 jsdsrc
->textSpace
= 0;
64 jsdsrc
->status
= JSD_SOURCE_CLEARED
;
65 jsdsrc
->dirty
= JS_TRUE
;
66 jsdsrc
->alterCount
= jsdc
->sourceAlterCount
++ ;
67 jsdsrc
->doingEval
= JS_FALSE
;
71 _appendText(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
,
72 const char* text
, size_t length
)
74 #define MEMBUF_GROW 1000
76 uintN neededSize
= jsdsrc
->textLength
+ length
;
78 if( neededSize
> jsdsrc
->textSpace
)
83 /* if this is the first alloc, the req might be all that's needed*/
84 if( ! jsdsrc
->textSpace
)
87 iNewSize
= (neededSize
* 5 / 4) + MEMBUF_GROW
;
89 newBuf
= (char*) realloc(jsdsrc
->text
, iNewSize
);
92 /* try again with the minimal size really asked for */
93 iNewSize
= neededSize
;
94 newBuf
= (char*) realloc(jsdsrc
->text
, iNewSize
);
98 _clearText( jsdc
, jsdsrc
);
99 jsdsrc
->status
= JSD_SOURCE_FAILED
;
104 jsdsrc
->text
= newBuf
;
105 jsdsrc
->textSpace
= iNewSize
;
108 memcpy(jsdsrc
->text
+ jsdsrc
->textLength
, text
, length
);
109 jsdsrc
->textLength
+= length
;
113 static JSDSourceText
*
114 _newSource(JSDContext
* jsdc
, const char* url
)
116 JSDSourceText
* jsdsrc
= (JSDSourceText
*)calloc(1,sizeof(JSDSourceText
));
120 jsdsrc
->url
= (char*) url
; /* already a copy */
121 jsdsrc
->status
= JSD_SOURCE_INITED
;
122 jsdsrc
->dirty
= JS_TRUE
;
123 jsdsrc
->alterCount
= jsdc
->sourceAlterCount
++ ;
129 _destroySource(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
131 JS_ASSERT(NULL
== jsdsrc
->text
); /* must _clearText() first */
137 _removeSource(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
139 JS_REMOVE_LINK(&jsdsrc
->links
);
140 _clearText(jsdc
, jsdsrc
);
141 _destroySource(jsdc
, jsdsrc
);
144 static JSDSourceText
*
145 _addSource(JSDContext
* jsdc
, const char* url
)
147 JSDSourceText
* jsdsrc
= _newSource(jsdc
, url
);
150 JS_INSERT_LINK(&jsdsrc
->links
, &jsdc
->sources
);
155 _moveSourceToFront(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
157 JS_REMOVE_LINK(&jsdsrc
->links
);
158 JS_INSERT_LINK(&jsdsrc
->links
, &jsdc
->sources
);
162 _moveSourceToRemovedList(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
164 _clearText(jsdc
, jsdsrc
);
165 JS_REMOVE_LINK(&jsdsrc
->links
);
166 JS_INSERT_LINK(&jsdsrc
->links
, &jsdc
->removedSources
);
170 _removeSourceFromRemovedList( JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
172 JS_REMOVE_LINK(&jsdsrc
->links
);
173 _destroySource( jsdc
, jsdsrc
);
177 _isSourceInSourceList(JSDContext
* jsdc
, JSDSourceText
* jsdsrcToFind
)
179 JSDSourceText
*jsdsrc
;
181 for( jsdsrc
= (JSDSourceText
*)jsdc
->sources
.next
;
182 jsdsrc
!= (JSDSourceText
*)&jsdc
->sources
;
183 jsdsrc
= (JSDSourceText
*)jsdsrc
->links
.next
)
185 if( jsdsrc
== jsdsrcToFind
)
191 /* compare strings in a case insensitive manner with a length limit
195 strncasecomp (const char* one
, const char * two
, int n
)
200 for(pA
=one
, pB
=two
;; pA
++, pB
++)
207 tmp
= tolower(*pA
) - tolower(*pB
);
213 static char file_url_prefix
[] = "file:";
214 #define FILE_URL_PREFIX_LEN (sizeof file_url_prefix - 1)
217 jsd_BuildNormalizedURL( const char* url_string
)
219 char *new_url_string
;
224 if (!strncasecomp(url_string
, file_url_prefix
, FILE_URL_PREFIX_LEN
) &&
225 url_string
[FILE_URL_PREFIX_LEN
+ 0] == '/' &&
226 url_string
[FILE_URL_PREFIX_LEN
+ 1] == '/') {
227 new_url_string
= JS_smprintf("%s%s",
229 url_string
+ FILE_URL_PREFIX_LEN
+ 2);
231 new_url_string
= strdup(url_string
);
233 return new_url_string
;
236 /***************************************************************************/
239 jsd_DestroyAllSources( JSDContext
* jsdc
)
241 JSDSourceText
*jsdsrc
;
244 for( jsdsrc
= (JSDSourceText
*)jsdc
->sources
.next
;
245 jsdsrc
!= (JSDSourceText
*)&jsdc
->sources
;
248 next
= (JSDSourceText
*)jsdsrc
->links
.next
;
249 _removeSource( jsdc
, jsdsrc
);
252 for( jsdsrc
= (JSDSourceText
*)jsdc
->removedSources
.next
;
253 jsdsrc
!= (JSDSourceText
*)&jsdc
->removedSources
;
256 next
= (JSDSourceText
*)jsdsrc
->links
.next
;
257 _removeSourceFromRemovedList( jsdc
, jsdsrc
);
263 jsd_IterateSources(JSDContext
* jsdc
, JSDSourceText
**iterp
)
265 JSDSourceText
*jsdsrc
= *iterp
;
268 jsdsrc
= (JSDSourceText
*)jsdc
->sources
.next
;
269 if( jsdsrc
== (JSDSourceText
*)&jsdc
->sources
)
271 *iterp
= (JSDSourceText
*)jsdsrc
->links
.next
;
276 jsd_FindSourceForURL(JSDContext
* jsdc
, const char* url
)
278 JSDSourceText
*jsdsrc
;
280 for( jsdsrc
= (JSDSourceText
*)jsdc
->sources
.next
;
281 jsdsrc
!= (JSDSourceText
*)&jsdc
->sources
;
282 jsdsrc
= (JSDSourceText
*)jsdsrc
->links
.next
)
284 if( 0 == strcmp(jsdsrc
->url
, url
) )
291 jsd_GetSourceURL(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
297 jsd_GetSourceText(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
,
298 const char** ppBuf
, intN
* pLen
)
300 *ppBuf
= jsdsrc
->text
;
301 *pLen
= jsdsrc
->textLength
;
306 jsd_ClearSourceText(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
308 if( JSD_SOURCE_INITED
!= jsdsrc
->status
&&
309 JSD_SOURCE_PARTIAL
!= jsdsrc
->status
)
311 _clearText(jsdc
, jsdsrc
);
316 jsd_GetSourceStatus(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
318 return jsdsrc
->status
;
322 jsd_IsSourceDirty(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
324 return jsdsrc
->dirty
;
328 jsd_SetSourceDirty(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
, JSBool dirty
)
330 jsdsrc
->dirty
= dirty
;
334 jsd_GetSourceAlterCount(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
336 return jsdsrc
->alterCount
;
340 jsd_IncrementSourceAlterCount(JSDContext
* jsdc
, JSDSourceText
* jsdsrc
)
342 return jsdsrc
->alterCount
= jsdc
->sourceAlterCount
++;
345 /***************************************************************************/
347 #if defined(DEBUG) && 0
348 void DEBUG_ITERATE_SOURCES( JSDContext
* jsdc
)
350 JSDSourceText
* iterp
= NULL
;
351 JSDSourceText
* jsdsrc
= NULL
;
354 while( NULL
!= (jsdsrc
= jsd_IterateSources(jsdc
, &iterp
)) )
360 JSDStreamStatus status
;
363 url
= JSD_GetSourceURL(jsdc
, jsdsrc
);
364 dirty
= JSD_IsSourceDirty(jsdc
, jsdsrc
);
365 status
= JSD_GetSourceStatus(jsdc
, jsdsrc
);
366 gotSrc
= JSD_GetSourceText(jsdc
, jsdsrc
, &text
, &len
);
368 dummy
= 0; /* gives us a line to set breakpoint... */
372 #define DEBUG_ITERATE_SOURCES(x) ((void)x)
375 /***************************************************************************/
378 jsd_NewSourceText(JSDContext
* jsdc
, const char* url
)
380 JSDSourceText
* jsdsrc
;
381 const char* new_url_string
;
383 JSD_LOCK_SOURCE_TEXT(jsdc
);
386 new_url_string
= url
; /* we take ownership of alloc'd string */
388 new_url_string
= jsd_BuildNormalizedURL(url
);
390 if( ! new_url_string
)
393 jsdsrc
= jsd_FindSourceForURL(jsdc
, new_url_string
);
397 if( jsdsrc
->doingEval
)
400 free((char*)new_url_string
);
402 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
406 _moveSourceToRemovedList(jsdc
, jsdsrc
);
409 jsdsrc
= _addSource( jsdc
, new_url_string
);
411 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
417 jsd_AppendSourceText(JSDContext
* jsdc
,
418 JSDSourceText
* jsdsrc
,
419 const char* text
, /* *not* zero terminated */
421 JSDSourceStatus status
)
423 JSD_LOCK_SOURCE_TEXT(jsdc
);
425 if( jsdsrc
->doingEval
)
427 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
431 if( ! _isSourceInSourceList( jsdc
, jsdsrc
) )
433 _removeSourceFromRemovedList( jsdc
, jsdsrc
);
434 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
438 if( text
&& length
&& ! _appendText( jsdc
, jsdsrc
, text
, length
) )
440 jsdsrc
->dirty
= JS_TRUE
;
441 jsdsrc
->alterCount
= jsdc
->sourceAlterCount
++ ;
442 jsdsrc
->status
= JSD_SOURCE_FAILED
;
443 _moveSourceToRemovedList(jsdc
, jsdsrc
);
444 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
448 jsdsrc
->dirty
= JS_TRUE
;
449 jsdsrc
->alterCount
= jsdc
->sourceAlterCount
++ ;
450 jsdsrc
->status
= status
;
451 DEBUG_ITERATE_SOURCES(jsdc
);
452 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
457 jsd_AppendUCSourceText(JSDContext
* jsdc
,
458 JSDSourceText
* jsdsrc
,
459 const jschar
* text
, /* *not* zero terminated */
461 JSDSourceStatus status
)
463 #define UNICODE_TRUNCATE_BUF_SIZE 1024
464 static char* buf
= NULL
;
465 int remaining
= length
;
468 return jsd_AppendSourceText(jsdc
, jsdsrc
, NULL
, 0, status
);
470 JSD_LOCK_SOURCE_TEXT(jsdc
);
473 buf
= malloc(UNICODE_TRUNCATE_BUF_SIZE
);
476 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
480 while(remaining
&& jsdsrc
) {
481 int bytes
= JS_MIN(remaining
, UNICODE_TRUNCATE_BUF_SIZE
);
483 for(i
= 0; i
< bytes
; i
++)
484 buf
[i
] = (const char) *(text
++);
485 jsdsrc
= jsd_AppendSourceText(jsdc
,jsdsrc
,
490 if(jsdsrc
&& status
!= JSD_SOURCE_PARTIAL
)
491 jsdsrc
= jsd_AppendSourceText(jsdc
, jsdsrc
, NULL
, 0, status
);
493 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
497 /* convienence function for adding complete source of url in one call */
499 jsd_AddFullSourceText(JSDContext
* jsdc
,
500 const char* text
, /* *not* zero terminated */
504 JSDSourceText
* jsdsrc
;
506 JSD_LOCK_SOURCE_TEXT(jsdc
);
508 jsdsrc
= jsd_NewSourceText(jsdc
, url
);
510 jsdsrc
= jsd_AppendSourceText(jsdc
, jsdsrc
,
511 text
, length
, JSD_SOURCE_PARTIAL
);
513 jsdsrc
= jsd_AppendSourceText(jsdc
, jsdsrc
,
514 NULL
, 0, JSD_SOURCE_COMPLETED
);
516 JSD_UNLOCK_SOURCE_TEXT(jsdc
);
518 return jsdsrc
? JS_TRUE
: JS_FALSE
;
521 /***************************************************************************/
524 jsd_StartingEvalUsingFilename(JSDContext
* jsdc
, const char* url
)
526 JSDSourceText
* jsdsrc
;
528 /* NOTE: We leave it locked! */
529 JSD_LOCK_SOURCE_TEXT(jsdc
);
531 jsdsrc
= jsd_FindSourceForURL(jsdc
, url
);
535 #ifndef JSD_LOWLEVEL_SOURCE
536 JS_ASSERT(! jsdsrc
->doingEval
);
539 jsdsrc
->doingEval
= JS_TRUE
;
544 jsd_FinishedEvalUsingFilename(JSDContext
* jsdc
, const char* url
)
546 JSDSourceText
* jsdsrc
;
548 /* NOTE: We ASSUME it is locked! */
550 jsdsrc
= jsd_FindSourceForURL(jsdc
, url
);
554 #ifndef JSD_LOWLEVEL_SOURCE
556 * when using this low level source addition, this jsdsrc might
557 * not have existed before the eval, but does exist now (without
560 JS_ASSERT(jsdsrc
->doingEval
);
563 jsdsrc
->doingEval
= JS_FALSE
;
566 JSD_UNLOCK_SOURCE_TEXT(jsdc
);