DIR * opendir(char *filename) { DIR *dirp = typecalloc(DIR); long status; if (dirp == 0) return (0); zfab = cc$rms_fab; zfab.fab$l_fop = FAB$M_NAM; zfab.fab$l_nam = &znam; /* FAB => NAM block */ zfab.fab$l_dna = (global_g_val(GMDALL_VERSIONS) ? "*.*;*" : "*.*;"); zfab.fab$b_dns = strlen(zfab.fab$l_dna); zfab.fab$l_fna = filename; zfab.fab$b_fns = strlen(filename); znam = cc$rms_nam; znam.nam$b_ess = NAM$C_MAXRSS; znam.nam$l_esa = zesa; znam.nam$b_rss = NAM$C_MAXRSS; znam.nam$l_rsa = zrsa; if (sys$parse(&zfab) != RMS$_NORMAL) { (void) closedir(dirp); dirp = 0; } return (dirp); }
PRIVATE void append_close_tag ARGS3( char*, tagname, HT_tagspec**, head, HT_tagspec**, tail) { int idx, nattr; HTTag* tag; HT_tagspec* subj; idx = html_src_tag_index(tagname); tag = HTML_dtd.tags+idx; nattr = tag->number_of_attributes; if (idx == -1) { fprintf(stderr, "internal error: previous check didn't find bad HTML tag %s", tagname); exit_immediately(EXIT_FAILURE); } subj = typecalloc(HT_tagspec); subj->element = idx; subj->present = typecallocn(BOOL, nattr); subj->value = typecallocn(char *, nattr); subj->start = FALSE; #ifdef USE_COLOR_STYLE subj->class_name = NULL; #endif if (!*head) { *head = subj; *tail = subj; } else { (*tail)->next = subj; *tail = subj; } }
HTStyleSheet *HTStyleSheetNew(void) { HTStyleSheet *self = typecalloc(HTStyleSheet); if (self == NULL) outofmem(__FILE__, "HTStyleSheetNew"); return self; }
/* Create a chunk with a certain allocation unit ** -------------- */ PUBLIC HTChunk * HTChunkCreate ARGS1 (int,grow) { HTChunk * ch = typecalloc(HTChunk); if (ch == NULL) outofmem(__FILE__, "creation of chunk"); HTChunkInit (ch, grow); return ch; }
int HTAddRule(HTRuleOp op, const char *pattern, const char *equiv, const char *cond_op, const char *cond) { /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */ rule *temp; char *pPattern = NULL; temp = typecalloc(rule); if (temp == NULL) outofmem(__FILE__, "HTAddRule"); if (equiv) { /* Two operands */ char *pEquiv = NULL; StrAllocCopy(pEquiv, equiv); temp->equiv = pEquiv; } else { temp->equiv = 0; } if (cond_op) { StrAllocCopy(temp->condition_op, cond_op); StrAllocCopy(temp->condition, cond); } StrAllocCopy(pPattern, pattern); temp->pattern = pPattern; temp->op = op; if (equiv) { CTRACE((tfp, "Rule: For `%s' op %d `%s'", pattern, op, equiv)); } else { CTRACE((tfp, "Rule: For `%s' op %d", pattern, op)); } if (cond_op) { CTRACE((tfp, "\t%s %s\n", cond_op, NONNULL(cond))); } else { CTRACE((tfp, "\n")); } if (!rules) { #ifdef LY_FIND_LEAKS atexit(HTClearRules); #endif } #ifdef PUT_ON_HEAD temp->next = rules; rules = temp; #else temp->next = 0; if (rule_tail) rule_tail->next = temp; else rules = temp; rule_tail = temp; #endif return 0; }
static BI_NODE * new_elapsed(BI_DATA * a) { BI_NODE *p; beginDisplay(); if ((p = typecalloc(BI_NODE)) != 0) { BI_DATA *q = &(p->value); if ((BI_KEY(p) = strmalloc(a->bi_key)) == 0 || (q->data = typecalloc(ELAPSED_DATA)) == 0) { old_elapsed(p); p = 0; } } endofDisplay(); return p; }
PRIVATE HTChildAnchor * HTChildAnchor_new ARGS1( HTParentAnchor0 *, parent) { HTChildAnchor *p = typecalloc(HTChildAnchor); if (p == NULL) outofmem(__FILE__, "HTChildAnchor_new"); p->parent = parent; /* parent reference */ return p; }
/* ** Purpose: Capture all requests to free information and also ** remove items from the allocation list. ** Arguments: vp_Alloced The memory to free. ** cp_File The file calling free. ** ssi_Line The line of cp_File calling free. ** Return Value: void ** Remarks/Portability/Dependencies/Restrictions: ** If the pointer value is invalid, then an item will be added ** to the list and nothing else is done. ** I really like the name of this function and one day hope ** that Lynx is Leak Free. ** Revision History: ** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe */ PUBLIC void LYLeakFree ARGS3( void *, vp_Alloced, CONST char *, cp_File, CONST short, ssi_Line) { AllocationList *ALp_free; if (LYfind_leaks == FALSE) { free(vp_Alloced); return; } /* * Find the pointer in the allocated list. * If not found, bad pointer. * If found, free list item and vp_Allloced. */ ALp_free = FindInList(vp_Alloced); if (ALp_free == NULL) { /* * Create the final entry before exiting marking this error. * If unable to allocate more memory just exit. */ AllocationList *ALp_new = typecalloc(AllocationList); if (ALp_new == NULL) { exit(EXIT_FAILURE); } /* * Set up the information, no memory need be allocated * for the file name since it is a static string. */ ALp_new->vp_Alloced = NULL; ALp_new->vp_BadRequest = vp_Alloced; ALp_new->SL_memory.cp_FileName = cp_File; ALp_new->SL_memory.ssi_LineNumber = ssi_Line; /* * Add the entry to the list and then return. */ AddToList(ALp_new); return; } else { /* * Free off the memory. * Take entry out of allocation list. */ CountFrees(ALp_free->st_Bytes); RemoveFromList(ALp_free); FREE(ALp_free); FREE(vp_Alloced); } }
/* The creation method */ PUBLIC HTStream * HTNetToText ARGS1(HTStream *, sink) { HTStream* me = typecalloc(HTStream); if (me == NULL) outofmem(__FILE__, "NetToText"); me->isa = &NetToTextClass; me->had_cr = NO; me->sink = sink; return me; }
/* ** Purpose: Add information about new allocation to the list, ** after a call to malloc or calloc or an equivalent ** function which may or may not have already created ** a list entry. ** Arguments: vp_malloc The pointer to newly allocated memory. ** Arguments: st_bytes The size of the allocation requested ** in bytes. ** cp_File The file from which the request for ** allocation came from. ** ssi_Line The line number in cp_File where the ** allocation request came from. ** Return Value: void * A pointer to the allocated memory or NULL on ** failure. ** Remarks/Portability/Dependencies/Restrictions: ** If no memory is allocated, then no entry is added to the ** allocation list. ** Revision History: ** 1999-02-08 created, modelled after LYLeakMalloc - kw */ PUBLIC AllocationList *LYLeak_mark_malloced ARGS4( void *, vp_malloced, size_t, st_bytes, CONST char *, cp_File, CONST short, ssi_Line) { AllocationList *ALp_new = NULL; if (LYfind_leaks == FALSE) return NULL; /* * The actual allocation has already been done! * * Only on successful allocation do we track any information. */ if (vp_malloced != NULL) { /* * See if there is already an entry. If so, just * update the source location info. */ ALp_new = FindInList(vp_malloced); if (ALp_new) { ALp_new->SL_memory.cp_FileName = cp_File; ALp_new->SL_memory.ssi_LineNumber = ssi_Line; return(ALp_new); } /* * Further allocate memory to store the information. * Just return on failure to allocate more. */ ALp_new = typecalloc(AllocationList); if (ALp_new == NULL) { return(NULL); } /* * Copy over the relevant information. */ ALp_new->vp_Alloced = vp_malloced; ALp_new->st_Bytes = st_bytes; ALp_new->SL_memory.cp_FileName = cp_File; ALp_new->SL_memory.ssi_LineNumber = ssi_Line; /* * Add the new item to the allocation list. */ AddToList(ALp_new); } return(ALp_new); }
static SGML_dtd *load_flatfile(FILE *input) { AttrType *attr_types = 0; SGML_dtd *result = 0; size_t n; size_t number_of_attrs = 0; size_t number_of_tags = 0; HTTag *tag; int code; code = fscanf(input, "%d attr_types\n", &number_of_attrs); if (code && number_of_attrs && (attr_types = typecallocn(AttrType, number_of_attrs + 1)) != 0) { for (n = 0; n < number_of_attrs; ++n) { if (!load_flat_AttrType(input, attr_types + n, n)) { break; } } } code = fscanf(input, "%d tags\n", &number_of_tags); if (code == 1) { if ((result = typecalloc(SGML_dtd)) != 0 && (result->tags = typecallocn(HTTag, (number_of_tags + 2))) != 0) { for (n = 0; n < number_of_tags; ++n) { if (load_flat_HTTag(input, n, &(result->tags[n]), attr_types)) { result->number_of_tags = (n + 1); } else { break; } } tag = 0; for (n = 0; n < number_of_tags; ++n) { if (result->tags[n].name != 0 && !strcmp(result->tags[n].name, "OBJECT")) { tag = result->tags + number_of_tags; *tag = result->tags[n]; tag->contents = SGML_MIXED; tag->flags = Tgf_strict; break; } } if (tag == 0) { fprintf(stderr, "Did not find OBJECT tag\n"); result = 0; } } } return result; }
/* Creation Methods ** ================ ** ** Do not use "new" by itself outside this module. In order to enforce ** consistency, we insist that you furnish more information about the ** anchor you are creating : use newWithParent or newWithAddress. */ PRIVATE HTParentAnchor0 * HTParentAnchor0_new ARGS2( CONST char *, address, short, hash) { HTParentAnchor0 *newAnchor = typecalloc(HTParentAnchor0); if (newAnchor == NULL) outofmem(__FILE__, "HTParentAnchor0_new"); newAnchor->parent = newAnchor; /* self */ StrAllocCopy(newAnchor->address, address); newAnchor->adult_hash = hash; return(newAnchor); }
/* ** Purpose: Capture allocations by calloc (stdlib.h) and ** save relevant information in a list. ** Arguments: st_number The number of items to allocate. ** st_bytes The size of each item. ** cp_File The file which wants to allocation. ** ssi_Line The line number in cp_File requesting ** the allocation. ** Return Value: void * The allocated memory, or NULL on failure as ** per calloc (stdlib.h) ** Remarks/Portability/Dependencies/Restrictions: ** If no memory can be allocated, then no entry will be added ** to the list. ** Revision History: ** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe */ PUBLIC void *LYLeakCalloc ARGS4( size_t, st_number, size_t, st_bytes, CONST char *, cp_File, CONST short, ssi_Line) { void *vp_calloc; if (LYfind_leaks == FALSE) return (void *)calloc(st_number, st_bytes); /* * Allocate the requested memory. */ vp_calloc = (void *)calloc(st_number, st_bytes); CountMallocs(st_bytes); /* * Only if the allocation was a success do we track information. */ if (vp_calloc != NULL) { /* * Allocate memory for the item to be in the list. * If unable, just return. */ AllocationList *ALp_new = typecalloc(AllocationList); if (ALp_new == NULL) { return(vp_calloc); } /* * Copy over the relevant information. * There is no need to allocate memory for the file * name as it is a static string anyway. */ ALp_new->st_Sequence = count_mallocs; ALp_new->vp_Alloced = vp_calloc; ALp_new->st_Bytes = (st_number * st_bytes); ALp_new->SL_memory.cp_FileName = cp_File; ALp_new->SL_memory.ssi_LineNumber = ssi_Line; /* * Add the item to the allocation list. */ AddToList(ALp_new); } return(vp_calloc); }
PUBLIC HTChunk * HTChunkCreateMayFail ARGS2 (int,grow, int,failok) { HTChunk * ch = typecalloc(HTChunk); if (ch == NULL) { if (!failok) { outofmem(__FILE__, "creation of chunk"); } else { return ch; } } HTChunkInit (ch, grow); ch->failok = failok; return ch; }
/* ** Purpose: Capture allocations using malloc (stdlib.h) and track ** the information in a list. ** Arguments: st_bytes The size of the allocation requested ** in bytes. ** cp_File The file from which the request for ** allocation came from. ** ssi_Line The line number in cp_File where the ** allocation request came from. ** Return Value: void * A pointer to the allocated memory or NULL on ** failure as per malloc (stdlib.h) ** Remarks/Portability/Dependencies/Restrictions: ** If no memory is allocated, then no entry is added to the ** allocation list. ** Revision History: ** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe */ PUBLIC void *LYLeakMalloc ARGS3( size_t, st_bytes, CONST char *, cp_File, CONST short, ssi_Line) { void *vp_malloc; if (LYfind_leaks == FALSE) return (void *)malloc(st_bytes); /* * Do the actual allocation. */ vp_malloc = (void *)malloc(st_bytes); CountMallocs(st_bytes); /* * Only on successful allocation do we track any information. */ if (vp_malloc != NULL) { /* * Further allocate memory to store the information. * Just return on failure to allocate more. */ AllocationList *ALp_new = typecalloc(AllocationList); if (ALp_new == NULL) { return(vp_malloc); } /* * Copy over the relevant information. * There is no need to allocate more memory for the * file name as it is a static string anyhow. */ ALp_new->st_Sequence = count_mallocs; ALp_new->vp_Alloced = vp_malloc; ALp_new->st_Bytes = st_bytes; ALp_new->SL_memory.cp_FileName = cp_File; ALp_new->SL_memory.ssi_LineNumber = ssi_Line; /* * Add the new item to the allocation list. */ AddToList(ALp_new); } return(vp_malloc); }
/* Create a chunk with a certain allocation unit and ensured size ** -------------- */ PUBLIC HTChunk * HTChunkCreate2 ARGS2 (int,grow, size_t, needed) { HTChunk * ch = typecalloc(HTChunk); if (ch == NULL) outofmem(__FILE__, "HTChunkCreate2"); HTChunkInit (ch, grow); if (needed > 0) { ch->allocated = needed-1 - ((needed-1) % ch->growby) + ch->growby; /* Round up */ CTRACE((tfp, "HTChunkCreate2: requested %d, allocate %d\n", (int) needed, ch->allocated)); ch->data = typecallocn(char, ch->allocated); if (!ch->data) outofmem(__FILE__, "HTChunkCreate2 data"); }
static BI_NODE * new_tags(BI_DATA * a) { BI_NODE *p; beginDisplay(); if ((p = typecalloc(BI_NODE)) != 0) { p->value = *a; if ((BI_KEY(p) = strmalloc(a->bi_key)) == 0) { old_tags(p); p = 0; } } endofDisplay(); return p; }
PRIVATE HTParentAnchor * HTParentAnchor_new ARGS1( HTParentAnchor0 *, parent) { HTParentAnchor *newAnchor = typecalloc(HTParentAnchor); if (newAnchor == NULL) outofmem(__FILE__, "HTParentAnchor_new"); newAnchor->parent = parent; /* cross reference */ parent->info = newAnchor; /* cross reference */ newAnchor->address = parent->address; /* copy pointer */ newAnchor->isISMAPScript = FALSE; /* Lynx appends ?0,0 if TRUE. - FM */ newAnchor->isHEAD = FALSE; /* HEAD request if TRUE. - FM */ newAnchor->safe = FALSE; /* Safe. - FM */ newAnchor->no_cache = FALSE; /* no-cache? - FM */ newAnchor->inBASE = FALSE; /* duplicated from HTML.c/h */ newAnchor->content_length = 0; /* Content-Length. - FM */ return(newAnchor); }
/* Create a chunk with a certain allocation unit and ensured size * -------------- */ HTChunk *HTChunkCreate2(int grow, size_t needed) { HTChunk *ch = typecalloc(HTChunk); if (ch == NULL) outofmem(__FILE__, "HTChunkCreate2"); HTChunkInit(ch, grow); if (needed > 0) { /* Round up */ ch->allocated = (int) (needed - 1 - ((needed - 1) % ch->growby) + (unsigned) ch->growby); CTRACE((tfp, "HTChunkCreate2: requested %d, allocate %u\n", (int) needed, (unsigned) ch->allocated)); ch->data = typecallocn(char, (unsigned) ch->allocated); if (!ch->data) outofmem(__FILE__, "HTChunkCreate2 data"); }
/* Define a presentation system command for a content-type ** ------------------------------------------------------- */ PUBLIC void HTSetPresentation ARGS6( CONST char *, representation, CONST char *, command, double, quality, double, secs, double, secs_per_byte, long int, maxbytes) { HTPresentation * pres = typecalloc(HTPresentation); if (pres == NULL) outofmem(__FILE__, "HTSetPresentation"); pres->rep = HTAtom_for(representation); pres->rep_out = WWW_PRESENT; /* Fixed for now ... :-) */ pres->converter = HTSaveAndExecute; /* Fixed for now ... */ pres->quality = (float) quality; pres->secs = (float) secs; pres->secs_per_byte = (float) secs_per_byte; pres->maxbytes = maxbytes; pres->command = NULL; StrAllocCopy(pres->command, command); /* * Memory leak fixed. * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe */ if (!HTPresentations) { HTPresentations = HTList_new(); #ifdef LY_FIND_LEAKS atexit(HTFreePresentations); #endif } if (strcmp(representation, "*")==0) { FREE(default_presentation); default_presentation = pres; } else { HTList_addObject(HTPresentations, pres); } }
/* Define a built-in function for a content-type ** --------------------------------------------- */ PUBLIC void HTSetConversion ARGS7( CONST char *, representation_in, CONST char *, representation_out, HTConverter*, converter, float, quality, float, secs, float, secs_per_byte, long int, maxbytes) { HTPresentation * pres = typecalloc(HTPresentation); if (pres == NULL) outofmem(__FILE__, "HTSetConversion"); pres->rep = HTAtom_for(representation_in); pres->rep_out = HTAtom_for(representation_out); pres->converter = converter; pres->command = NULL; /* Fixed */ pres->quality = quality; pres->secs = secs; pres->secs_per_byte = secs_per_byte; pres->maxbytes = maxbytes; pres->command = NULL; /* * Memory Leak fixed. * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe */ if (!HTPresentations) { HTPresentations = HTList_new(); #ifdef LY_FIND_LEAKS atexit(HTFreePresentations); #endif } HTList_addObject(HTPresentations, pres); }
/* ** We store charset info in the HTParentAnchor object, for several ** "stages". (See UCDefs.h) ** A stream method is supposed to know what stage in the model it is. ** ** General model MIME -> parser -> structured -> HText ** e.g., text/html ** from HTTP: HTMIME.c -> SGML.c -> HTML.c -> GridText.c ** text/plain ** from file: HTFile.c -> HTPlain.c -> GridText.c ** ** The lock/set_by is used to lock e.g. a charset set by an explicit ** HTTP MIME header against overriding by a HTML META tag - the MIME ** header has higher priority. Defaults (from -assume_.. options etc.) ** will not override charset explicitly given by server. ** ** Some advantages of keeping this in the HTAnchor: ** - Global variables are bad. ** - Can remember a charset given by META tag when toggling to SOURCE view. ** - Can remember a charset given by <A CHARSET=...> href in another doc. ** ** We don't modify the HTParentAnchor's charset element ** here, that one will only be set when explicitly given. */ PUBLIC LYUCcharset * HTAnchor_getUCInfoStage ARGS2( HTParentAnchor *, me, int, which_stage) { if (me && !me->UCStages) { int i; int chndl = UCLYhndl_for_unspec; /* always >= 0 */ UCAnchorInfo * stages = typecalloc(UCAnchorInfo); if (stages == NULL) outofmem(__FILE__, "HTAnchor_getUCInfoStage"); for (i = 0; i < UCT_STAGEMAX; i++) { stages->s[i].C.MIMEname = ""; stages->s[i].LYhndl = -1; } if (me->charset) { chndl = UCGetLYhndl_byMIME(me->charset); if (chndl < 0) chndl = UCLYhndl_for_unrec; if (chndl < 0) /* ** UCLYhndl_for_unrec not defined :-( ** fallback to UCLYhndl_for_unspec which always valid. */ chndl = UCLYhndl_for_unspec; /* always >= 0 */ } memcpy(&stages->s[UCT_STAGE_MIME].C, &LYCharSet_UC[chndl], sizeof(LYUCcharset)); stages->s[UCT_STAGE_MIME].lock = UCT_SETBY_DEFAULT; stages->s[UCT_STAGE_MIME].LYhndl = chndl; me->UCStages = stages; } if (me) { return( &me->UCStages->s[which_stage].C); } return(NULL); }
/* ** Purpose: Capture any realloc (stdlib.h) calls in order to ** properly keep track of our run time allocation ** table. ** Arguments: vp_Alloced The previously allocated block of ** memory to resize. If NULL, ** realloc works just like ** malloc. ** st_newBytes The new size of the chunk of memory. ** cp_File The file containing the realloc. ** ssi_Line The line containing the realloc in cp_File. ** Return Value: void * The new pointer value (could be the same) or ** NULL if unable to resize (old block ** still exists). ** Remarks/Portability/Dependencies/Restrictions: ** If unable to resize vp_Alloced, then no change in the ** allocation list will be made. ** If vp_Alloced is an invalid pointer value, the program will ** exit after one last entry is added to the allocation list. ** Revision History: ** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe */ PUBLIC void *LYLeakRealloc ARGS4( void *, vp_Alloced, size_t, st_newBytes, CONST char *, cp_File, CONST short, ssi_Line) { void *vp_realloc; AllocationList *ALp_renew; if (LYfind_leaks == FALSE) return (void *)realloc(vp_Alloced, st_newBytes); /* * If we are asked to resize a NULL pointer, this is just a * malloc call. */ if (vp_Alloced == NULL) { return(LYLeakMalloc(st_newBytes, cp_File, ssi_Line)); } /* * Find the current vp_Alloced block in the list. * If NULL, this is an invalid pointer value. */ ALp_renew = FindInList(vp_Alloced); if (ALp_renew == NULL) { /* * Track the invalid pointer value and then exit. * If unable to allocate, just exit. */ auto AllocationList *ALp_new = typecalloc(AllocationList); if (ALp_new == NULL) { exit(EXIT_FAILURE); } /* * Set the information up; no need to allocate file name * since it is a static string. */ ALp_new->vp_Alloced = NULL; ALp_new->vp_BadRequest = vp_Alloced; ALp_new->SL_realloc.cp_FileName = cp_File; ALp_new->SL_realloc.ssi_LineNumber = ssi_Line; /* * Add the item to the list. * Exit. */ AddToList(ALp_new); exit(EXIT_FAILURE); } /* * Perform the resize. * If not NULL, record the information. */ vp_realloc = (void *)realloc(vp_Alloced, st_newBytes); CountMallocs(st_newBytes); CountFrees(ALp_renew->st_Bytes); if (vp_realloc != NULL) { ALp_renew->st_Sequence = count_mallocs; ALp_renew->vp_Alloced = vp_realloc; ALp_renew->st_Bytes = st_newBytes; /* * Update the realloc information, too. * No need to allocate file name, static string. */ ALp_renew->SL_realloc.cp_FileName = cp_File; ALp_renew->SL_realloc.ssi_LineNumber = ssi_Line; } return(vp_realloc); }
/* * Utility for listing visited links, making any repeated links the most * current in the list. - FM */ void LYAddVisitedLink(DocInfo *doc) { VisitedLink *tmp; HTList *cur; const char *title = (doc->title ? doc->title : NO_TITLE); if (isEmpty(doc->address)) { PrevVisitedLink = NULL; return; } /* * Exclude POST or HEAD replies, and bookmark, menu or list files. - FM */ if (doc->post_data || doc->isHEAD || doc->bookmark || ( /* special url or a temp file */ (!StrNCmp(doc->address, "LYNX", 4) || !StrNCmp(doc->address, "file://localhost/", 17)))) { int related = 1; /* First approximation only */ if (LYIsUIPage(doc->address, UIP_HISTORY) || LYIsUIPage(doc->address, UIP_VLINKS) || LYIsUIPage(doc->address, UIP_SHOWINFO) || isLYNXMESSAGES(doc->address) || ((related = 0) != 0) || #ifdef DIRED_SUPPORT LYIsUIPage(doc->address, UIP_DIRED_MENU) || LYIsUIPage(doc->address, UIP_UPLOAD_OPTIONS) || LYIsUIPage(doc->address, UIP_PERMIT_OPTIONS) || #endif /* DIRED_SUPPORT */ LYIsUIPage(doc->address, UIP_PRINT_OPTIONS) || LYIsUIPage(doc->address, UIP_DOWNLOAD_OPTIONS) || LYIsUIPage(doc->address, UIP_OPTIONS_MENU) || isLYNXEDITMAP(doc->address) || isLYNXKEYMAP(doc->address) || LYIsUIPage(doc->address, UIP_LIST_PAGE) || #ifdef USE_ADDRLIST_PAGE LYIsUIPage(doc->address, UIP_ADDRLIST_PAGE) || #endif LYIsUIPage(doc->address, UIP_CONFIG_DEF) || LYIsUIPage(doc->address, UIP_LYNXCFG) || isLYNXCOOKIE(doc->address) || LYIsUIPage(doc->address, UIP_TRACELOG)) { if (!related) PrevVisitedLink = NULL; return; } } if (!Visited_Links) { Visited_Links = HTList_new(); #ifdef LY_FIND_LEAKS atexit(Visited_Links_free); #endif Latest_last.prev_latest = &Latest_first; Latest_first.next_latest = &Latest_last; Latest_last.next_latest = NULL; /* Find bugs quick! */ Latest_first.prev_latest = NULL; Last_by_first = Latest_tree = First_tree = NULL; } cur = Visited_Links; while (NULL != (tmp = (VisitedLink *) HTList_nextObject(cur))) { if (!strcmp(NonNull(tmp->address), NonNull(doc->address))) { PrevVisitedLink = PrevActiveVisitedLink = tmp; /* Already visited. Update the last-visited info. */ if (tmp->next_latest == &Latest_last) /* optimization */ return; /* Remove from "latest" chain */ tmp->prev_latest->next_latest = tmp->next_latest; tmp->next_latest->prev_latest = tmp->prev_latest; /* Insert at the end of the "latest" chain */ Latest_last.prev_latest->next_latest = tmp; tmp->prev_latest = Latest_last.prev_latest; tmp->next_latest = &Latest_last; Latest_last.prev_latest = tmp; return; } } if ((tmp = typecalloc(VisitedLink)) == NULL) outofmem(__FILE__, "LYAddVisitedLink"); StrAllocCopy(tmp->address, doc->address); LYformTitle(&(tmp->title), title); /* First-visited chain */ HTList_appendObject(Visited_Links, tmp); /* At end */ tmp->prev_first = Last_by_first; Last_by_first = tmp; /* Tree structure */ if (PrevVisitedLink) { VisitedLink *a = PrevVisitedLink; VisitedLink *b = a->next_tree; int l = PrevVisitedLink->level; /* Find last on the deeper levels */ while (b && b->level > l) a = b, b = b->next_tree; if (!b) /* a == Latest_tree */ Latest_tree = tmp; tmp->next_tree = a->next_tree; a->next_tree = tmp; tmp->level = PrevVisitedLink->level + 1; } else { if (Latest_tree) Latest_tree->next_tree = tmp; tmp->level = 0; tmp->next_tree = NULL; Latest_tree = tmp; } PrevVisitedLink = PrevActiveVisitedLink = tmp; if (!First_tree) First_tree = tmp; /* "latest" chain */ Latest_last.prev_latest->next_latest = tmp; tmp->prev_latest = Latest_last.prev_latest; tmp->next_latest = &Latest_last; Latest_last.prev_latest = tmp; return; }
/* ** Purpose: A wrapper around StrAllocVsprintf (the workhorse of ** HTSprintf/HTSprintf0, implemented in HTString.c) that ** tries to make sure that our allocation list is always ** properly updated, whether StrAllocVsprintf itself was ** compiled with memory tracking or not (or even a mixture, ** like tracking the freeing but not the new allocation). ** Some source files can be compiled with LY_FIND_LEAKS_EXTENDED ** in effect while others only have LY_FIND_LEAKS in effect, ** and as long as HTString.c is complied with memory tracking ** (of either kind) string objects allocated by HTSprintf/ ** HTSprintf0 (or otherwise) can be passed around among them and ** manipulated both ways. ** Arguments: dest As for StrAllocVsprintf. ** cp_File The source file of the caller (i.e. the ** caller of HTSprintf/HTSprintf0, hopefully). ** ssi_Line The line of cp_File calling. ** inuse,fmt,ap As for StrAllocVsprintf. ** Return Value: The char pointer to resulting string, as set ** by StrAllocVsprintf, or ** NULL if dest==0 (wrong use!). ** Remarks/Portability/Dependencies/Restrictions: ** The price for generality is severe inefficiency: several ** list lookups are done to be on the safe side. ** We don't get he real allocation size, only a minimum based ** on the string length of the result. So the amount of memory ** leakage may get underestimated. ** If *dest is an invalid pointer value on entry (i.e. was not ** tracked), the program will exit after one last entry is added ** to the allocation list. ** If StrAllocVsprintf fails to return a valid string via the ** indirect string pointer (its first parameter), invalid memory ** access will result and the program will probably terminate ** with a signal. This can happen if, on entry, *dest is NULL ** and fmt is empty or NULL, so just Don't Do That. ** Revision History: ** 1999-02-11 created kw ** 1999-10-15 added comments kw */ PRIVATE char * LYLeakSAVsprintf ARGS6( char **, dest, CONST char *, cp_File, CONST short, ssi_Line, size_t, inuse, CONST char *, fmt, va_list *, ap) { AllocationList *ALp_old; void *vp_oldAlloced; CONST char * old_cp_File = __FILE__; short old_ssi_Line = __LINE__; if (!dest) return NULL; if (LYfind_leaks == FALSE) { StrAllocVsprintf(dest, inuse, fmt, ap); return (*dest); } vp_oldAlloced = *dest; if (!vp_oldAlloced) { StrAllocVsprintf(dest, inuse, fmt, ap); LYLeak_mark_malloced(*dest, strlen(*dest) + 1, cp_File, ssi_Line); return(*dest); } else { void * vp_realloced; ALp_old = FindInList(vp_oldAlloced); if (ALp_old == NULL) { /* * Track the invalid pointer value and then exit. * If unable to allocate, just exit. */ auto AllocationList *ALp_new = typecalloc(AllocationList); if (ALp_new == NULL) { exit(EXIT_FAILURE); } /* * Set the information up; no need to allocate file name * since it is a static string. */ ALp_new->vp_Alloced = NULL; ALp_new->vp_BadRequest = vp_oldAlloced; ALp_new->SL_realloc.cp_FileName = cp_File; ALp_new->SL_realloc.ssi_LineNumber = ssi_Line; /* * Add the item to the list. * Exit. */ AddToList(ALp_new); exit(EXIT_FAILURE); } old_cp_File = ALp_old->SL_memory.cp_FileName; old_ssi_Line = ALp_old->SL_memory.ssi_LineNumber; /* * DO THE REAL WORK, by calling StrAllocVsprintf. * If result is not NULL, record the information. */ StrAllocVsprintf(dest, inuse, fmt, ap); vp_realloced = (void *)*dest; if (vp_realloced != NULL) { AllocationList *ALp_new = FindInList(vp_realloced); if (!ALp_new) { /* Look up again, list may have changed! - kw */ ALp_old = FindInList(vp_oldAlloced); if (ALp_old == NULL) { LYLeak_mark_malloced(*dest, strlen(*dest) + 1, cp_File, ssi_Line); return(*dest); } mark_realloced(ALp_old, *dest, strlen(*dest) + 1, cp_File, ssi_Line); return(*dest); } if (vp_realloced == vp_oldAlloced) { ALp_new->SL_memory.cp_FileName = old_cp_File; ALp_new->SL_memory.ssi_LineNumber = old_ssi_Line; ALp_new->SL_realloc.cp_FileName = cp_File; ALp_new->SL_realloc.ssi_LineNumber = ssi_Line; return(*dest); } /* Look up again, list may have changed! - kw */ ALp_old = FindInList(vp_oldAlloced); if (ALp_old == NULL) { ALp_new->SL_memory.cp_FileName = old_cp_File; ALp_new->SL_memory.ssi_LineNumber = old_ssi_Line; ALp_new->SL_realloc.cp_FileName = cp_File; ALp_new->SL_realloc.ssi_LineNumber = ssi_Line; } else { ALp_new->SL_memory.cp_FileName = old_cp_File; ALp_new->SL_memory.ssi_LineNumber = old_ssi_Line; ALp_new->SL_realloc.cp_FileName = cp_File; ALp_new->SL_realloc.ssi_LineNumber = ssi_Line; } } return(*dest); } }