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 ( strcasecmp( 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 ( strcasecmp( 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 /***********************************************************************
108 * GlobalAddAtom (USER.268)
111 /* important! don't forget to unlock semaphores before return */
112 ATOM
GlobalAddAtom( LPCSTR str
)
119 dprintf_atom(stddeb
,"GlobalAddAtom(%p)\n", str
);
120 if ((unsigned) str
< MIN_STR_ATOM
) /* MS-windows convention */
121 return (ATOM
) (unsigned) str
;
122 if (str
[0] == '#') { /* wine convention */
123 atom
= (ATOM
) atoi(&str
[1]);
124 return (atom
<MIN_STR_ATOM
) ? atom
: 0;
126 dprintf_atom(stddeb
,"GlobalAddAtom(\"%s\")\n",str
);
128 DDE_IPC_init(); /* will initialize only if needed */
130 shm_write_wait(main_block
->sem
);
132 atom_idx
=FindHash(str
);
135 /* use "return" only at the end so semaphore handling is done only once */
137 /* unless table full and item not found */
138 switch (atom_ofs
= ATOM_OFS(atom_idx
)) {
140 case EMPTY
: /* need to allocate new atom */
141 atom_ofs
= shm_FragmentAlloc(&main_block
->block
,
142 strlen(str
)+sizeof(AtomData
));
144 break; /* no more memory (atom==0) */
145 ATOM_OFS(atom_idx
)=atom_ofs
;
146 ptr
=OFS2AtomData_ptr(atom_ofs
);
147 strcpy(ptr
->str
,str
);
149 atom
=(ATOM
)(atom_idx
+MIN_STR_ATOM
);
151 default : /* has to update existing atom */
152 OFS2AtomData_ptr(atom_ofs
)->count
++;
153 atom
=(ATOM
)(atom_idx
+MIN_STR_ATOM
);
154 } /* end of switch */
156 shm_write_signal(main_block
->sem
);
160 /***********************************************************************
161 * GlobalDeleteAtom (USER.269)
164 ATOM
GlobalDeleteAtom( ATOM atom
)
168 AtomData_ptr atom_ptr
;
169 ATOM retval
=(ATOM
) 0;
171 dprintf_atom(stddeb
,"GlobalDeleteAtom(\"%d\")\n",(int)atom
);
172 atom_idx
=(int)atom
- MIN_STR_ATOM
;
177 DDE_IPC_init(); /* will initialize only if needed */
179 shm_write_wait(main_block
->sem
);
180 /* return used only once from here on -- for semaphore simplicity */
181 switch (atom_ofs
=ATOM_OFS(atom_idx
)) {
184 fprintf(stderr
,"trying to free unallocated atom %d\n", atom
);
188 atom_ptr
=OFS2AtomData_ptr(atom_ofs
);
189 if ( --atom_ptr
->count
== 0) {
190 shm_FragmentFree(&main_block
->block
,atom_ofs
);
191 ATOM_OFS(atom_idx
)=DELETED
;
195 shm_write_signal(main_block
->sem
);
199 /***********************************************************************
200 * GlobalFindAtom (USER.270)
202 ATOM
GlobalFindAtom( LPCSTR str
)
207 dprintf_atom(stddeb
,"GlobalFindAtom(%p)\n", str
);
208 if ((unsigned) str
< MIN_STR_ATOM
) /* MS-windows convention */
209 return (ATOM
) (unsigned) str
;
210 if (str
[0] == '#') { /* wine convention */
211 ATOM atom
= (ATOM
) atoi(&str
[1]);
212 return (atom
<MIN_STR_ATOM
) ? atom
: 0;
214 dprintf_atom(stddeb
,"GlobalFindAtom(\"%s\")\n",str
);
216 DDE_IPC_init(); /* will initialize only if needed */
218 shm_read_wait(main_block
->sem
);
219 atom_idx
=FindHash(str
);
221 atom_ofs
=ATOM_OFS(atom_idx
); /* is it free ? */
224 shm_read_signal(main_block
->sem
);
226 if (atom_ofs
==EMPTY
|| atom_ofs
==DELETED
)
229 return (ATOM
)(atom_idx
+MIN_STR_ATOM
);
232 /***********************************************************************
233 * GlobalGetAtomName (USER.271)
235 WORD
GlobalGetAtomName( ATOM atom
, LPSTR buffer
, short count
)
237 int atom_idx
, atom_ofs
;
239 /* temporary buffer to hold maximum "#65535\0" */
242 if (count
<2) /* no sense to go on */
244 atom_idx
=(int)atom
- MIN_STR_ATOM
;
246 if (atom_idx
< 0) { /* word atom */
247 /* use wine convention... */
248 sprintf(str_num
,"#%d%n",(int)atom
,&size
);
249 if (size
+1>count
) { /* overflow ? */
250 /* truncate the string */
254 strcpy(buffer
,str_num
);
258 DDE_IPC_init(); /* will initialize only if needed */
261 shm_read_wait(main_block
->sem
);
262 atom_ofs
=ATOM_OFS(atom_idx
);
263 if (atom_ofs
==EMPTY
|| atom_ofs
==DELETED
) {
264 fprintf(stderr
,"GlobalGetAtomName: illegal atom=%d\n",(int)atom
);
266 } else { /* non empty entry */
267 /* string length will be at most count-1, find actual size */
268 sprintf(buffer
,"%.*s%n",count
-1, OFS2AtomStr(atom_ofs
), &size
);
270 shm_read_signal(main_block
->sem
);