/* userlist_user_gender: * returns user's gender */ enum vqp_gender userlist_user_gender(const char * user_name) { struct userlist_entry * entry; ASSERT_RETURNVALIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash), 0); entry = userlist_entry_by_name(user_name); return entry ? entry->gender: VQP_GENDER_MALE; }
/* userlist_remove: * removes specified user from userlist * params: * @explicit_part - non-0 if the user left explicitly (he notified us of that) */ void userlist_remove(const char * user_name, int explicit_remove) { struct userlist_entry * entry; ASSERT_RETURNIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash)); entry = userlist_entry_by_name(user_name); if(entry) { const char * enum_cb_data[2]; /* notify DB that the user has become offline * (if the user is in db list) */ HANDLE hContact = contacts_find_contact(user_name); if(hContact) contacts_set_contact_status(hContact, ID_STATUS_OFFLINE); /* update user's chatroom: * leave every channel the user is in */ enum_cb_data[0] = user_name; enum_cb_data[1] = (const char *)explicit_remove; chanlist_enum( entry->chanlist, userlist_remove_channel_part_enum, (void*)enum_cb_data); /* remove user entry from the hash and free it */ hashtable_remove(s_userlistHash, (void*)user_name, 1); } }
/* userlist_user_swversion: * returns' user's software version */ unsigned int userlist_user_swversion(const char * user_name) { struct userlist_entry * entry; ASSERT_RETURNVALIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash), 0); entry = userlist_entry_by_name(user_name); return entry ? entry->swversion: VQCHAT_UNDEF_SWVERSION; }
/* userlist_user_is_chat_open: * returns if we have a private chat opened with the user */ int userlist_user_is_chat_open(const char * user_name) { struct userlist_entry * entry; ASSERT_RETURNVALIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash), 0); entry = userlist_entry_by_name(user_name); return entry ? entry->chat_open: 0; }
void userlist_user_chanlist_update( const char * user_name, const char * updated_chanlist) { struct userlist_entry * entry; ASSERT_RETURNIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash)); entry = userlist_entry_by_name(user_name); if(entry) { const char * enum_fn_data[2]; char * new_chanlist = chanlist_copy(updated_chanlist); /* join new previously-missing channels */ chanlist_enum( new_chanlist, userlist_user_chanlist_update_join_enum_fn, (void*)user_name); /* leave the channels that the user is off */ enum_fn_data[0] = new_chanlist; enum_fn_data[1] = user_name; chanlist_enum( entry->chanlist, userlist_user_chanlist_update_part_enum_fn, (void*)enum_fn_data); /* free chanlists */ chanlist_free(new_chanlist); } }
BOOL H_DeleteFileW_setup(H_DeleteFileWStruct *data) { HMODULE hMod; VALIDPTR(hMod = GetModuleHandle("KERNEL32.DLL")) VALIDPTR(data->pGetCurrentProcessId = (GetCurrentProcessId_t)GetProcAddress(hMod, "GetCurrentProcessId")) return TRUE; }
/* userlist_user_set_chat_open: * sets wherether the chat is open with the user */ void userlist_user_set_chat_open(const char * user_name, int set_chat_open) { struct userlist_entry * entry; ASSERT_RETURNIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash)); entry = userlist_entry_by_name(user_name); if(entry) entry->chat_open = set_chat_open; }
/* userlist_user_status: * returns miranda's status for user, or ID_STATUS_OFFLINE, if not found */ int userlist_user_status(const char * user_name) { struct userlist_entry * entry; ASSERT_RETURNVALIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash), ID_STATUS_OFFLINE); entry = userlist_entry_by_name(user_name); return entry ? user_status_by_vqp_status(entry->vqp_status): ID_STATUS_OFFLINE; }
/* userlist_user_chanlist: * returns users' chanlist */ const char * userlist_user_chanlist(const char * user_name) { struct userlist_entry * entry; ASSERT_RETURNVALIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash), 0); entry = userlist_entry_by_name(user_name); return entry ? entry->chanlist: NULL; }
static int userlist_remove_channel_part_enum( const char * channel, void * enum_data) { const char * user = ((const char **)enum_data)[0], * explicit_part = ((const char **)enum_data)[1]; ASSERT_RETURNVALIFFAIL(VALIDPTR(channel) && VALIDPTR(enum_data), 0); userlist_user_channel_part(user, channel, (int)explicit_part); return 1; }
/* chanlist_merge: * Merges two chanlists, the result adds to chanlist_dst * and it is what returns. * * Note that chanlist_src might get modified in the process * thus it is non-const, but it is kept unmodified after return. */ static int chanlist_merge_enum_fn(const char * channel, void * enum_data) { char ** p_dst_chanlist = (char **)enum_data; ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), 0); ASSERT_RETURNVALIFFAIL(VALIDPTR(p_dst_chanlist), 0); *p_dst_chanlist = chanlist_add(*p_dst_chanlist, channel); return 1; /* keep enumerating */ }
/* userlist_add: * adds user to userlist, updates it's info if the user already exists */ void userlist_add( const char * name, enum vqp_status vqp_status, enum vqp_gender gender, const vqp_uuid_t * p_uuid, enum vqp_codepage codepage, unsigned int swversion, vqp_addr_t addr, int add_to_log) { struct userlist_entry * entry; HANDLE hContact; ASSERT_RETURNIFFAIL(VALIDPTR(name) && VALIDPTR(s_userlistHash)); entry = userlist_entry_by_name(name); if(entry) { entry->alive = 1; userlist_entry_status_change( name, entry, vqp_status, gender, "", add_to_log); return; } /* setup new user list entry struct */ entry = malloc(sizeof(struct userlist_entry)); entry->vqp_status = vqp_status; entry->codepage = codepage; entry->gender = gender; entry->swversion = swversion; entry->uuid = *p_uuid; entry->addr = addr; entry->alive = 1; entry->chat_open = 0; entry->chanlist = NULL; /* insert into the hash table */ hashtable_insert(s_userlistHash, strdup(name), entry); /* notify DB that the user has become visible (if he is on list) * and set user ip */ hContact = contacts_find_contact(name); if(hContact) { contacts_set_contact_status(hContact, user_status_by_vqp_status(vqp_status)); contacts_set_contact_addr(hContact, addr); } /* every user of QuickChat/VypressChat networks is a member * of #Main channel */ userlist_user_channel_join(name, VQCHAT_MAIN_CHANNEL, add_to_log); }
void userlist_user_channel_join( const char * user_name, const char * channel, int add_to_log) { struct userlist_entry * entry; ASSERT_RETURNIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash)); entry = userlist_entry_by_name(user_name); if(entry && !chanlist_contains(entry->chanlist, channel)) { /* add channel to user's channel list */ entry->chanlist = chanlist_add(entry->chanlist, channel); /* notify chatrooms */ chatroom_channel_user_join(channel, user_name, add_to_log); } }
/* chanlist_shift: * removes the first channel from the list and returns * the chanlist without the channel * * params: * @p_chanlist - chanlist to shift the channel off * returns: * NULL, if the chanlist is empty * malloc'ed channel name shifted from the chanlist */ char * chanlist_shift(char ** p_chanlist) { char * next, * new_chanlist, * channel; /* check that the channel is valid */ ASSERT_RETURNVALIFFAIL(VALIDPTR(p_chanlist), NULL); if(!chanlist_is_valid(*p_chanlist, 0)) return NULL; /* check if chanlist is empty */ if(*p_chanlist==NULL) return NULL; /* get pointer to the next channel in the list */ next = strchr(*p_chanlist + 1, '#'); /* make a copy of the rest as new chanlist */ new_chanlist = chanlist_copy(next); /* finish channel name with a '\0' */ if(next) *next = '\0'; channel = *p_chanlist; memmove(channel, channel + 1, strlen(channel)); *p_chanlist = new_chanlist; return channel; }
static void CALLBACK userlist_remove_unreplied_cb( HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { struct userlist_remove_unreplied_info_struct info; int i; char * r_nickname; ASSERT_RETURNIFFAIL(VALIDPTR(s_userlistHash)); /* perform enumeration to find the unreplied ones */ info.dead_keys = malloc( sizeof(void*) * hashtable_count(s_userlistHash)); info.dead_key_count = 0; hashtable_enumerate( s_userlistHash, userlist_remove_unreplied_enum_fn, (void*)&info); /* quietly remove those dead */ for(i = 0; i < info.dead_key_count; i++) { userlist_remove(info.dead_keys[i], 0); free(info.dead_keys[i]); } /* free leftovers */ free(info.dead_keys); /* send another user refresh list request to the network */ r_nickname = util_utf2vqp(user_codepage(), user_nickname()); msgloop_send(vqp_msg_refresh_req(s_vqpLink, r_nickname, user_codepage()), 0); free(r_nickname); }
void userlist_status_change( const char * user_name, enum vqp_status new_user_status, enum vqp_gender new_user_gender, const char * status_text, int add_to_log) { struct userlist_entry * entry; ASSERT_RETURNIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash)); entry = userlist_entry_by_name(user_name); if(entry) { userlist_entry_status_change( user_name, entry, new_user_status, new_user_gender, status_text, add_to_log); } }
APIRET OS2ENTRY DosFindNext( HDIR hDir, PVOID pFindBuf, ULONG cbFindBuf, PULONG pcFileNames) { WIN32_FIND_DATA FindData; /* Win32 Find data (returned by FindFirstFile) */ APIRET rc; if (!VALIDPTR(pFindBuf)) { fprintf(stderr, "DosFindNext: pfindbuf - %p\n", pFindBuf); return ERROR_INVALID_PARAMETER; } if (cbFindBuf < sizeof(FILEFINDBUF3)) { fprintf(stderr, "DosFindNext: unsupported buffer size - %d\n", cbFindBuf); return ERROR_INVALID_PARAMETER; } if (!VALIDPTR(pcFileNames)) { fprintf(stderr, "DosFindNext: pcFileNames - %p\n", pcFileNames); return ERROR_INVALID_PARAMETER; } if (FindNextFile((HANDLE)hDir, &FindData)) { PFILEFINDBUF3 pfindbuf = (PFILEFINDBUF3)pFindBuf; memcpy(pfindbuf->achName, FindData.cFileName, pfindbuf->cchName = strlen(FindData.cFileName) + 1); pfindbuf->cbFile = pfindbuf->cbFileAlloc = FindData.nFileSizeHigh > 0 ? 0xffffffff : FindData.nFileSizeLow; pfindbuf->attrFile = ConvertAttributes(FindData.dwFileAttributes); *(PULONG)(&pfindbuf->fdateCreation) = ConvertFileTime(&FindData.ftCreationTime); *(PULONG)(&pfindbuf->fdateLastAccess) = ConvertFileTime(&FindData.ftLastAccessTime); *(PULONG)(&pfindbuf->fdateLastWrite) = ConvertFileTime(&FindData.ftLastWriteTime); pfindbuf->oNextEntryOffset = 0; *pcFileNames = 1; rc = NO_ERROR; } else rc = GetLastError(); return rc; }
/* userlist_user_codepage_vqp: * tries to get or guess codepage for specified user name * (on vypresschat it tries UTF8 encoding first, on qChat - locale) */ enum vqp_codepage userlist_user_codepage_vqp(const char * vqp_user_name) { struct userlist_entry * entry; ASSERT_RETURNVALIFFAIL(VALIDPTR(vqp_user_name), VQCHAT_VQP_COMPAT_CODEPAGE); entry = userlist_entry_by_name_vqp(vqp_user_name); return entry ? entry->codepage: VQCHAT_VQP_COMPAT_CODEPAGE; }
void userlist_user_set_codepage(const char * user_name, enum vqp_codepage codepage) { struct userlist_entry * entry; ASSERT_RETURNIFFAIL(VALIDPTR(user_name)); entry = userlist_entry_by_name(user_name); if(entry) entry->codepage = codepage; }
/* userlist_user_channel_part: * this will make the user leave the specified channel * parameters: * @explicit_part - specifies whether the user left explicitly, or because * of refresh timeout */ void userlist_user_channel_part( const char * user_name, const char * channel, int explicit_part) { struct userlist_entry * entry; ASSERT_RETURNIFFAIL(VALIDPTR(user_name) && VALIDPTR(s_userlistHash)); ASSERT_RETURNIFFAIL(VALIDPTR(channel)); entry = userlist_entry_by_name(user_name); if(entry && chanlist_contains(entry->chanlist, channel)) { /* remove channel from user's channel list */ entry->chanlist = chanlist_remove(entry->chanlist, channel); /* notify chatrooms */ chatroom_channel_user_part(channel, user_name, explicit_part); } }
/* chanlist_add: * Creates a channel list (if chanlist==NULL) with a new channel * or add a new one to the end. * Checks if the channel is already in the list. * The result channel list string should look like: * "#channel1#channel2...#channelN". * An empty channel list is a (char*)NULL. */ char * chanlist_add(char * chanlist, const char * channel) { char * new_chanlist; int cl_len, ch_len; ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), chanlist); if(chanlist_find_channel(chanlist, channel, NULL, NULL)) return chanlist; /* the chanlist doesn't contain the new channel: * append it to the end */ ch_len = strlen(channel); ASSERT_RETURNVALIFFAIL(ch_len!=0, chanlist); if(chanlist) { /* get the length of channel list, note that an empty chanlist * MUST be (char*)NULL, and an non-empty chanlist must be at * least 2 chars in length ("#a") and have '#' at the beginning */ cl_len = strlen(chanlist); ASSERT_RETURNVALIFFAIL( cl_len >= 2 && chanlist[0]=='#', chanlist); } else { cl_len = 0; } /* allocate space for a previous channel list, plus a # character * and new channel, and a terminator */ new_chanlist = malloc((cl_len + ch_len + 1 + 1) * sizeof(char)); ASSERT_RETURNVALIFFAIL(new_chanlist!=NULL, chanlist); if(chanlist) { /* strcpy(new_chanlist, chanlist); */ memcpy(new_chanlist, chanlist, cl_len); free(chanlist); } new_chanlist[cl_len] = '#'; /* strcat(new_chanlist, "#"); */ /* strcat(new_chanlist, channel); */ memcpy(new_chanlist + cl_len + 1, channel, ch_len + 1); return new_chanlist; }
/* chanlist_make_vqp_chanlist: * allocates a vqp chanlist (the same as chanlist, only with '#' at the end) * and always non-NULL */ char * chanlist_make_vqp_chanlist(const char * chanlist) { int cl_len; char * vqp_chanlist; cl_len = chanlist ? strlen(chanlist): 0; vqp_chanlist = malloc(cl_len + 2); ASSERT_RETURNVALIFFAIL(VALIDPTR(vqp_chanlist), NULL); if(chanlist) memcpy(vqp_chanlist, chanlist, cl_len); /* append the '#' and '\0' terminator at the end */ vqp_chanlist[cl_len] = '#'; vqp_chanlist[cl_len + 1] = '\0'; return vqp_chanlist; }
/* chanlist_parse_vqp_chanlist: * makes a chanlist from vqp chanlist format */ char * chanlist_parse_vqp_chanlist(const char * vqp_chanlist) { int vqp_cl_len; char * chanlist; ASSERT_RETURNVALIFFAIL(VALIDPTR(vqp_chanlist), NULL); vqp_cl_len = strlen(vqp_chanlist); ASSERT_RETURNVALIFFAIL(vqp_cl_len != 0, NULL); /* vqp_chanlist must begin and end with '#' */ ASSERT_RETURNVALIFFAIL( vqp_chanlist[0]=='#' && vqp_chanlist[vqp_cl_len-1]=='#', NULL); /* make the chanlist (copy everything, except the last '#') */ chanlist = malloc(vqp_cl_len); memcpy(chanlist, vqp_chanlist, vqp_cl_len - 1); chanlist[vqp_cl_len - 1] ='\0'; return chanlist; }
/* msgloop_send: * msgloop_send should be used to send a message from miranda's * gui thread to send a message with qcs_msg loop. */ void msgloop_send(vqp_msg_t msg, int never_wait) { ASSERT_RETURNIFFAIL(VALIDPTR(msg)); /* send this message */ if(s_fLoopStarted && s_outputTimer) { /* check if we've sent a packet this tick, * and if we did, we'll have to wait for the next tick */ if(s_outputSentThisTick && !never_wait) { /* add msg to message queue for scheduler timer */ struct msgloop_message_list_entry * entry; entry = malloc(sizeof(struct msgloop_message_list_entry)); entry->msg = msg; entry->next = NULL; entry->prev = s_outputListHead; if(entry->prev) { entry->prev->next = entry; } else { s_outputListTail = entry; } s_outputListHead = entry; } else { QueueUserAPC(msgloop_apc_send_msg, s_hLoopThread, (ULONG_PTR)msg); s_outputSentThisTick = TRUE; } } else { if(s_outputSentThisTick && !never_wait) { Sleep(PACKET_OUTPUT_RATE); } vqp_link_send(msg); vqp_msg_free(msg); s_outputSentThisTick = TRUE; s_outputSentThisTickInTimer = FALSE; } }
/* chanlist_remove: * Removes a channel from chanlist and frees the resulting * chanlist, if it becomes empty (thus returning the (char*)NULL) */ char * chanlist_remove(char * chanlist, const char * channel) { char * cl_channel; int cl_len, ch_len; ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), chanlist); if(chanlist==NULL) return NULL; cl_channel = (char*)chanlist_find_channel( chanlist, channel, &cl_len, &ch_len); if(cl_channel == NULL) return chanlist; /* check if we need to free the list, (if it was the only channel) */ if(cl_len == ch_len + 1) { free(chanlist); return NULL; } /* if the channel was the last on the list, we put a terminator '\0' * and we're finished */ if((cl_channel - chanlist) + ch_len == cl_len) { *(cl_channel - 1) = '\0'; /* put '\0' on channel's '#' char */ return chanlist; } /* we need to move channels after cl_channel in the chanlist * to the place of cl_channel (including the '\0' terminator) */ memcpy(cl_channel, cl_channel + ch_len + 1, cl_len - (cl_channel - chanlist) - ch_len); return chanlist; }
/* chanlist_contains: * Returns non-0, if the chanlist contains the specified channel. */ int chanlist_contains(const char * chanlist, const char * channel) { ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), 0); return chanlist_find_channel(chanlist, channel, NULL, NULL) != NULL; }
int userlist_user_exists(const char * user_name) { ASSERT_RETURNVALIFFAIL( VALIDPTR(s_userlistHash) && VALIDPTR(user_name), 0); return userlist_entry_by_name(user_name) != NULL; }
APIRET OS2ENTRY DosQueryPathInfo( PCSZ pszPathName, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf) { APIRET rc; /* Return code. */ if (!VALIDPTR(pszPathName)) { fprintf(stderr, "DosQueryPathInfo: pszPathName is an invalid pointer - %p\n", pszPathName); return ERROR_INVALID_PARAMETER; } if (!VALIDPTR(pInfoBuf)) { fprintf(stderr, "DosQueryPathInfo: pInfoBuf is an invalid pointer - %p\n", pInfoBuf); return ERROR_INVALID_PARAMETER; } rc = ERROR_INVALID_PARAMETER; switch (ulInfoLevel) { case FIL_QUERYFULLNAME: { LPTSTR lpDummy; if (GetFullPathName(pszPathName, cbInfoBuf, pInfoBuf, &lpDummy) > 0) rc = NO_ERROR; else rc = GetLastError(); break; } case FIL_STANDARD: if (cbInfoBuf == sizeof(FILESTATUS3)) { WIN32_FILE_ATTRIBUTE_DATA fad; if (GetFileAttributesEx(pszPathName, GetFileExInfoStandard, &fad)) //W98, NT4 and above. { PFILESTATUS3 pfst3 = (PFILESTATUS3)(pInfoBuf); if (fad.nFileSizeHigh > 0) rc = ERROR_BAD_LENGTH; pfst3->cbFile = pfst3->cbFileAlloc = fad.nFileSizeLow; pfst3->attrFile = ConvertAttributes(fad.dwFileAttributes); *(PULONG)(&pfst3->fdateCreation) = ConvertFileTime(&fad.ftCreationTime); *(PULONG)(&pfst3->fdateLastAccess) = ConvertFileTime(&fad.ftLastAccessTime); *(PULONG)(&pfst3->fdateLastWrite) = ConvertFileTime(&fad.ftLastWriteTime); rc = NO_ERROR; } else rc = GetLastError(); } else fprintf(stderr, "DosQueryPathInfo: FIL_STANDARD - invalid structure size (cbInfoBuf=%d)\n", cbInfoBuf); break; default: fprintf(stderr, "DosQueryPathInfo: ulInfoLevel=%d not supported\n", ulInfoLevel); } return rc; }
void Agc_trace( SEGCTLPTR *heap_segments ) { AREA heap; AREA area; /* The current area being traced */ TRACINGSTACK tstack; /* Stack of areas to be traced */ SEGCTLPTR segctlp; SEGCTLPTR *segctlpp; SIZE temp; #ifndef A_FUNNY_STEPAREAPTR /* cop-out for weird architectures */ { /* Check that STEPAREAPTR works correctly on this machine for this nastily aligned structure */ /* If C compiler does tight packing, this could be a problem for the garbage collector */ ASSERT_DECL( struct { PTR p1; char c; PTR p2; } *ass_struct = NIL ) ASSERT_INIT( ( area.addr = (PTR)&ass_struct->c , area.size = sizeof(*ass_struct) ) ); ASSERT_INIT( STEPAREA( area ) ); ASSERT(area.addr == (PTR)&ass_struct->p2,Agc_collect,STEPAREA misbehaving); } #endif heap.addr = SEGSTART( *heap_segments ); heap.size = 0 ;/* inital values to be improved in loop*/ REPORT1(3, "%s\n", "Started trace... setting up bitmaps..."); for ( segctlp = *heap_segments; segctlp != NIL; segctlp = segctlp->next ) { REPORT6(6,"Agc_collect{mark}: segctlp=0x%p, elsize=%d, start=0x%p, end=0x%p, size=%d,els=%d\n", (void *)segctlp,SEGELSIZE(segctlp),(void *)SEGSTART(segctlp),(void *)SEGEND(segctlp),SEGSIZE(segctlp),SEGELS(segctlp)); if ( ! ( SEGELSIZE( segctlp ) > 0 && (char *)SEGEND( segctlp ) > (char *)SEGSTART( segctlp ) ) ) { /* Segment control information has been corrupted. */ /* Most likely this is because of a user scope/bound error, or CTRANS bug; though possibly a collector bug. */ GC_ERROR(HEAP segments corrupt); } if ( (char *)SEGSTART( segctlp ) < (char *)(heap.addr) ) { heap.size += (SIZE)((char *)(heap.addr) - (char *)SEGSTART( segctlp )); heap.addr = SEGSTART( segctlp ); } if ( SEGEND( segctlp ) > (PTR)((char *)(heap.addr)+heap.size) ) heap.size = (SIZE)((char *)SEGEND( segctlp ) - (char*)(heap.addr)); GRAB_BITMAP( segctlp->bitmap, SEGELS( segctlp ) + 3 ); SETMARK( segctlp->bitmap, SEGELS( segctlp ) + 0 ); ASSERT(!TSTMARK(segctlp->bitmap,SEGELS(segctlp)+1),Agc_collect,bitmap trailer set at grab); SETMARK( segctlp->bitmap, SEGELS( segctlp ) + 2 ); /* create an artificial endpoint which can be scanned to */ REPORT2(6,"Agc_collect:\t\tbitmap, ptr=0x%p, size=%d\n", (void *)(segctlp->bitmap), SEGELS( segctlp )); } REPORT2(5,"Agc_collect: heap address=0x%p, heap size=%d\n",(void *)heap.addr,heap.size); INIT_STACK(tstack); ASSERT_INIT(PUSH(tstack,(PTR)Agc_collect,-42)); /* Assertion mark */ PUSH(tstack, NIL, 0); /* identifies exhausted stack */ REPORT1(3, "%s\n", "Initialising stack scan..."); INIT_AREA(area); /* set area to first area to search - could also PUSH any additional areas (or use NEXT_AREA) */ do { for ( ; !NILAREA(area); /* POP() at end of loop as it may contain statements */ ) { REPORT3(6,"Agc_collect: AREA scan, ptr=0x%p -> 0x%p, size=%d\n", (void *)area.addr,(void *)((char *)area.addr+area.size),area.size); ASSERT(area.size >= 0 && area.size < 100*1024*1024 /* 100Mb */,Agc_collect,area size not sensible); for ( ; area.size >= sizeof(PTR); STEPAREA(area) ) { SIZE els, el_in_seg; PTR p = * (PTR *) area.addr; /* View word as a pointer */ REPORT3(9,"Agc_collect: AREA scan step, ptr=0x%p, size=%d, p=0x%p\n", (void *)area.addr,area.size,(void *)p); /* Continue loop if 'p' is unlikely to be a heap pointer. */ /* Keeping the loop small may help some machines with small instruction caches. */ if ( !VALIDPTR( p ) || !PTRINAREA(p,heap) ) continue; /* p is very likely to be a heap pointer */ for ( segctlpp = heap_segments; (segctlp = *segctlpp) != NIL; segctlpp = &((segctlp)->next )) { if ( (char *)p >= (char *)SEGSTART(segctlp) && (char *)p < (char *)SEGEND(segctlp) ) { /* Segment for heap pointer */ goto found_segment; } } /* Not a valid heap pointer */ continue; /* back to STEPAREA loop */ found_segment: REPORT3(6,"Agc_collect, found_segment: ptr=0x%p, segctlp=0x%p, elsize=%d\n", (void *)p,(void *)segctlp,SEGELSIZE(segctlp)); /* ** Move segment to front of segment list, to effect a 'cacheing' as in allocation. ** We believe that there is locality in types of heap pointers, ** (consider lists and trees) so it is likely that next ** lookup will immediately succeed. ** However a fast search startegy might be better ??? ** ** Note that typical programs only have a small number of segs, ** many of which are infrequently used. ** Multics Algol68 compiler uses 12 segs; ** ELLA uses ??? segs. */ *segctlpp = segctlp->next; segctlp->next = *heap_segments; *heap_segments = segctlp; #ifdef MUST_POINT_TO_WORD /* * Ignore pointers that are not word aligned, * unless in a segment of objects of size that is not a multiple of word. */ if ( (SEGELSIZE(segctlp) & (WORDSIZE-1)) == 0 && (((CODEDPTR)(p) & (WORDSIZE-1)) != 0) ) continue; /* p not to word aligned object, forget it */ #endif #ifdef MUST_POINT_TO_LWORD /* * Ignore pointers that are not long word aligned, * unless in a segment of objects of size that is not a multiple of long word. */ if ( (SEGELSIZE(segctlp) & (sizeof(long)-1)) == 0 && (((CODEDPTR)(p) & (sizeof(long)-1)) != 0) ) continue; /* p not to long aligned object, forget it */ #endif IDENTIFY_ALIGN_EL( p, el_in_seg, segctlp ); #ifdef MUST_POINT_TO_START /* Ignore pointers that point within objects */ /* This could be implemented more efficiently */ if ( p != * (PTR *) area.addr ) continue; /* p not to start of element, forget it */ #endif #ifdef NO_GCMARK els = 1; #else ANAL_DESC( els, p, area ); #endif REPORT3(6,"Agc_collect, aligned and analysed ptr: ptr=0x%p, element in seg=%d, elements=%d\n", (void *)p,el_in_seg,els); #ifdef A_GC_HALFWORD_ALIGNED /* Interpret this as half word aligned (2byte) DJS 8/12/94 */ /* +++ !!! ??? ** Crappy quick fix to keep elements word aligned for the Apollo ** (also done for Sun/68000, though it has not been proved that this is necessary). ** Apollo does not permit word objects to be aligned at any byte boundry, ** even though 68020/68030 does. This must be because C compiler generates ** strange code, or page faults for words that straddle page boundries are ** handled badly. */ if ( SEGELSIZE(segctlp) == 1 ) { if ( (long)p & 1 ) { p--; el_in_seg--; els++; } if ( els & 1 ) { els++; } if ( els <= 1 || els > SEGELS(segctlp) || p+(els*SEGELSIZE(segctlp)) > SEGEND(segctlp) ) { els = 2; } REPORT3(6,"Agc_collect, adjusted to: ptr=0x%x, element in seg=%d, elements=%d\n", p,el_in_seg,els); goto els_sensible; } #endif #ifdef A_GC_WORD_ALIGNED /* +++ !!! ??? ** Crappy quick fix to keep elements word aligned. */ if ( SEGELSIZE(segctlp) == 1 ) { if ( !WORDALIGNED(p) ) { int offset = (int)((CODEDPTR)p & (WORDSIZE-1)); p = (char *)p - offset; el_in_seg -= offset; els += offset; } if ( !WORDALIGNED(els) ) { els = (SIZE)ALIGN_NEXT(els,WORDSIZE); } if ( (els < WORDSIZE) || (els > SEGELS(segctlp)) || ((char *)p+(els*SEGELSIZE(segctlp)) > (char *)SEGEND(segctlp) )) { els = WORDSIZE; } REPORT3(6,"Agc_collect, adjusted to: ptr=0x%p, element in seg=%d, elements=%d\n", (void *)p,el_in_seg,els); goto els_sensible; } #endif /* 'els' may be a very silly number, check it is reasonable */ /* before doing arithmetic that may overflow. */ if ( els <= 1 || els > SEGELS(segctlp) || (char *)p+(els*SEGELSIZE(segctlp)) > (char *)SEGEND(segctlp) ) { /* els = 1; assumed in case array descriptor mis analysed, the ptr is still valid */ if ( !TSTMARK( segctlp->bitmap, el_in_seg ) ) { SETMARK( segctlp->bitmap, el_in_seg ); if ( SEGELSIZE(segctlp) >= PTRSIZE ) { /* need only scan elements that are large enough to hold pointer */ PUSH( tstack, p, SEGELSIZE(segctlp) ); REPORT2(6,"Agc_collect: PUSH( ptr=0x%p, size=%d )\n", (void *)p,SEGELSIZE(segctlp)); } } } else { els_sensible: CALCTSTMARKS( segctlp->bitmap, el_in_seg, els, temp ); if ( !RESTSTMARKS( segctlp->bitmap, el_in_seg, els, temp ) ) { /* ** At least one element in area has not been marked before. ** ** We could just mark and push unmarked areas, ** but this complicates logic for a fairly rare eventuality, ** mainly caused by the trimming of heap rows. */ SETMARKS( segctlp->bitmap, el_in_seg, els ); if ( SEGELSIZE(segctlp) >= PTRSIZE ) { /* need only scan elements that are large enough to hold pointer */ PUSH( tstack, p, els*SEGELSIZE(segctlp) ); REPORT2(6,"Agc_collect: PUSH( ptr=0x%p, size=%d )\n", (void *)p,els*SEGELSIZE(segctlp)); } } } } area = POP(tstack); } /* Stack is exhausted, replace end marker */ PUSH(tstack, NIL, 0); /* identifies exhausted stack */ NEXT_AREA(area); REPORT2(6,"Agc_collect: NEXT_AREA, ptr=0x%p, size=%d\n",(void *)area.addr,area.size); } while( area.addr != NIL ); area = POP(tstack); /* pop of (NIL, 0) to leave stack empty and tidy before calling FREE_STACK() */ ASSERT_INIT( area=POP(tstack) ); ASSERT(area.addr == (PTR)Agc_collect && area.size == -42,Agc_collect,tracing stack misuse); FREE_STACK(tstack); REPORT1(3, "%s\n", "End of trace"); }
APIRET OS2ENTRY DosFindFirst( PCSZ pszFileSpec, PHDIR phdir, ULONG flAttribute, PVOID pFindBuf, ULONG cbFindBuf, PULONG pcFileNames, ULONG ulInfoLevel) { WIN32_FIND_DATA FindData; /* Win32 Find data (returned by FindFirstFile) */ APIRET rc; if (!VALIDPTR(pszFileSpec)) { fprintf(stderr, "DosFindFirst: pszFileSpec - %p\n", pszFileSpec); return ERROR_INVALID_PARAMETER; } if (!VALIDPTR(phdir)) { fprintf(stderr, "DosFindFirst: phdir - %p\n", phdir); return ERROR_INVALID_PARAMETER; } if (!VALIDPTR(pFindBuf)) { fprintf(stderr, "DosFindFirst: pfindbuf - %p\n", pFindBuf); return ERROR_INVALID_PARAMETER; } if (!VALIDPTR(pcFileNames)) { fprintf(stderr, "DosFindFirst: pcFileNames - %p\n", pcFileNames); return ERROR_INVALID_PARAMETER; } if (*phdir != HDIR_CREATE) { fprintf(stderr, "DosFindFirst: *phdir != HDIR_CREATE - 0x%08x\n", *phdir); return ERROR_INVALID_PARAMETER; } switch (ulInfoLevel) { case FIL_STANDARD: if (cbFindBuf < sizeof(FILEFINDBUF3)) { fprintf(stderr, "DosFindFirst: unsupported buffer size - %d\n", cbFindBuf); return ERROR_INVALID_PARAMETER; } break; default: fprintf(stderr, "DosFindFirst: invalid infolevel %d\n", ulInfoLevel); return ERROR_INVALID_PARAMETER; } *phdir = (HDIR)FindFirstFile(pszFileSpec, &FindData); if (*phdir != (HDIR)INVALID_HANDLE_VALUE) { PFILEFINDBUF3 pfindbuf = (PFILEFINDBUF3)pFindBuf; memcpy(pfindbuf->achName, FindData.cFileName, pfindbuf->cchName = strlen(FindData.cFileName) + 1); pfindbuf->cbFile = pfindbuf->cbFileAlloc = FindData.nFileSizeHigh > 0 ? 0xffffffff : FindData.nFileSizeLow; pfindbuf->attrFile = ConvertAttributes(FindData.dwFileAttributes); *(PULONG)(&pfindbuf->fdateCreation) = ConvertFileTime(&FindData.ftCreationTime); *(PULONG)(&pfindbuf->fdateLastAccess) = ConvertFileTime(&FindData.ftLastAccessTime); *(PULONG)(&pfindbuf->fdateLastWrite) = ConvertFileTime(&FindData.ftLastWriteTime); pfindbuf->oNextEntryOffset = 0; *pcFileNames = 1; rc = NO_ERROR; } else rc = GetLastError(); return rc; }