1 /***************************************************************************
2 * Copyright 1995, Technion, Israel Institute of Technology
3 * Electrical Eng, Software Lab.
4 * Author: Michael Veksler.
5 ***************************************************************************
7 * Purpose : atom functionality for DDE
15 #include "shm_main_blk.h"
16 #include "shm_fragment.h"
24 } AtomData, *AtomData_ptr;
26 #define EMPTY 0 /* empty hash entry */
27 #define DELETED -1 /* deleted hash entry */
28 #define MIN_STR_ATOM 0xfc00
30 /* OFS2AtomData_ptr: extract AtomData_ptr from ofs */
31 #define OFS2AtomData_ptr(ofs) ((AtomData*)((int)&main_block->block+(ofs)))
33 /* OFS2AtomStr: find the string of the atom */
34 #define OFS2AtomStr(ofs) (OFS2AtomData_ptr(atom_ofs)->str)
36 /* offset of an atom according to index */
37 #define ATOM_OFS(idx) (main_block->atoms[idx])
39 /* rot_left: rotate (with wrap-around) */
40 static __inline__ int rot_left(unsigned var,int count)
42 return (var<<count) | (var>> (sizeof(var)-count));
44 /* find the entry in the atom table for this string */
45 static int FindHash(LPCSTR str) /* ignore str case */
49 int deleted=-1; /* hash for deleted entry */
52 /* get basic hash parameters */
53 for (i= hash1= hash2= 0; str[i] ; i++) {
54 hash1= rot_left(hash1,5) ^ toupper(str[i]);
55 hash2= rot_left(hash2,4) ^ toupper(str[i]);
59 atom_ofs=ATOM_OFS(hash1);
61 case EMPTY: /* empty atom entry */
63 case DELETED: /* deleted atom entry */
66 default : /* non empty atom entry */
67 if (lstrcmpi16( OFS2AtomStr(atom_ofs) , str) == 0)
68 return hash1; /* found string in atom table */
70 hash2%= DDE_ATOMS-1 ; /* hash2=0..(DDE_ATOMS-2) */
71 hash2++; /* hash2=1..(DDE_ATOMS-1) */
73 /* make jumps in the hash table by hash2 steps */
74 for (i=hash1+hash2 ; ; i+=hash2) {
75 /* i wraps around into j */
78 i=j; /* i wraps around */
81 /* here if covered all hash locations, and got back to beginning */
82 return deleted; /* return first empty entry - if any */
85 case EMPTY: /* empty atom entry */
87 case DELETED: /* deleted atom entry */
89 /* consider only the first deleted entry */
92 default : /* nonempty atom entry */
93 if (lstrcmpi16( OFS2AtomStr(atom_ofs) , str) == 0)
94 return i; /* found string in atom table */
99 void ATOM_GlobalInit(void)
103 for (i=0 ; i < DDE_ATOMS ; i++)
107 /***********************************************************************
111 /* important! don't forget to unlock semaphores before return */
112 ATOM DDE_GlobalAddAtom( SEGPTR name )
120 /* First check for integer atom */
122 if (!HIWORD(name)) return (ATOM)LOWORD(name);
124 str = (char *)PTR_SEG_TO_LIN( name );
127 ATOM atom= (ATOM) atoi(&str[1]);
128 return (atom<MIN_STR_ATOM) ? atom : 0;
131 TRACE(atom,"(\"%s\")\n",str);
133 DDE_IPC_init(); /* will initialize only if needed */
135 shm_write_wait(main_block->sem);
137 atom_idx=FindHash(str);
140 /* use "return" only at the end so semaphore handling is done only once */
142 /* unless table full and item not found */
143 switch (atom_ofs= ATOM_OFS(atom_idx)) {
145 case EMPTY: /* need to allocate new atom */
146 atom_ofs= shm_FragmentAlloc(&main_block->block,
147 strlen(str)+sizeof(AtomData));
149 break; /* no more memory (atom==0) */
150 ATOM_OFS(atom_idx)=atom_ofs;
151 ptr=OFS2AtomData_ptr(atom_ofs);
152 strcpy(ptr->str,str);
154 atom=(ATOM)(atom_idx+MIN_STR_ATOM);
156 default : /* has to update existing atom */
157 OFS2AtomData_ptr(atom_ofs)->count++;
158 atom=(ATOM)(atom_idx+MIN_STR_ATOM);
159 } /* end of switch */
161 shm_write_signal(main_block->sem);
165 /***********************************************************************
166 * DDE_GlobalDeleteAtom
169 ATOM DDE_GlobalDeleteAtom( ATOM atom )
173 AtomData_ptr atom_ptr;
174 ATOM retval=(ATOM) 0;
176 TRACE(atom,"(\"%d\")\n",(int)atom);
177 atom_idx=(int)atom - MIN_STR_ATOM;
182 DDE_IPC_init(); /* will initialize only if needed */
184 shm_write_wait(main_block->sem);
185 /* return used only once from here on -- for semaphore simplicity */
186 switch (atom_ofs=ATOM_OFS(atom_idx)) {
189 WARN(atom, "Trying to free unallocated atom %d\n", atom);
193 atom_ptr=OFS2AtomData_ptr(atom_ofs);
194 if ( --atom_ptr->count == 0) {
195 shm_FragmentFree(&main_block->block,atom_ofs);
196 ATOM_OFS(atom_idx)=DELETED;
200 shm_write_signal(main_block->sem);
204 /***********************************************************************
207 ATOM DDE_GlobalFindAtom( SEGPTR name )
213 TRACE(atom,"(%08lx)\n", name );
215 /* First check for integer atom */
217 if (!HIWORD(name)) return (ATOM)LOWORD(name);
219 str = (char *)PTR_SEG_TO_LIN( name );
222 ATOM atom= (ATOM) atoi(&str[1]);
223 return (atom<MIN_STR_ATOM) ? atom : 0;
225 TRACE(atom,"(\"%s\")\n",str);
227 DDE_IPC_init(); /* will initialize only if needed */
229 shm_read_wait(main_block->sem);
230 atom_idx=FindHash(str);
232 atom_ofs=ATOM_OFS(atom_idx); /* is it free ? */
235 shm_read_signal(main_block->sem);
237 if (atom_ofs==EMPTY || atom_ofs==DELETED)
240 return (ATOM)(atom_idx+MIN_STR_ATOM);
243 /***********************************************************************
244 * DDE_GlobalGetAtomName
246 WORD DDE_GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
248 int atom_idx, atom_ofs;
250 /* temporary buffer to hold maximum "#65535\0" */
253 if (count<2) /* no sense to go on */
255 atom_idx=(int)atom - MIN_STR_ATOM;
257 if (atom_idx < 0) { /* word atom */
258 /* use wine convention... */
259 sprintf(str_num,"#%d%n",(int)atom,&size);
260 if (size+1>count) { /* overflow ? */
261 /* truncate the string */
265 strcpy(buffer,str_num);
269 DDE_IPC_init(); /* will initialize only if needed */
272 shm_read_wait(main_block->sem);
273 atom_ofs=ATOM_OFS(atom_idx);
274 if (atom_ofs==EMPTY || atom_ofs==DELETED) {
275 WARN(atom,"Illegal atom=%d\n",(int)atom);
277 } else { /* non empty entry */
278 /* string length will be at most count-1, find actual size */
279 sprintf(buffer,"%.*s%n",count-1, OFS2AtomStr(atom_ofs), &size);
281 shm_read_signal(main_block->sem);
285 #endif /* CONFIG_IPC */