Bug Summary

File:gtx/textcb.c
Location:line 466, column 6
Description:Value stored to 'curr_ent' is never read

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10/*
11 * Implementation of the gator circular buffer package for its scrollable
12 * text object.
13 *
14 *------------------------------------------------------------------------*/
15
16#include <afsconfig.h>
17#include <afs/param.h>
18
19#include <roken.h>
20
21#include "gtxtextcb.h" /*Module interface */
22
23static int gator_textcb_debug; /*Is debugging output turned on? */
24
25/*------------------------------------------------------------------------
26 * gator_textcb_Init
27 *
28 * Description:
29 * Initialize the text circular buffer package.
30 *
31 * Arguments:
32 * a_debug : Should debugging output be turned on?
33 *
34 * Returns:
35 * Zero if successful,
36 * Error value otherwise.
37 *
38 * Environment:
39 * MUST BE THE FIRST ROUTINE CALLED FROM THIS PACKAGE.
40 *
41 * Side Effects:
42 * Just remembers if debugging output should be generated.
43 *------------------------------------------------------------------------*/
44
45int
46gator_textcb_Init(int a_debug)
47{ /*gator_textcb_Init */
48
49 static int initd; /*Have we been called already? */
50 static char rn[] = "gator_textcb_Init"; /*Routine name */
51
52 if (initd) {
53 fprintf(stderr__stderrp,
54 "[%s] Initialization routine called multiple times!!\n", rn);
55 return (0);
56 } else
57 initd = 1;
58
59 gator_textcb_debug = a_debug;
60 return (0);
61
62} /*gator_textcb_Init */
63
64/*------------------------------------------------------------------------
65 * gator_textcb_Create
66 *
67 * Description:
68 * Create a new circular buffer.
69 *
70 * Arguments:
71 * int a_maxEntriesStored : How many entries should it have?
72 * int a_maxCharsPerEntry : Max chars in each entry.
73 *
74 * Returns:
75 * Ptr to the fully-initialized circular buffer hdr if successful,
76 * Null pointer otherwise.
77 *
78 * Environment:
79 * Makes sure the lock structure is properly initialized.
80 *
81 * Side Effects:
82 * As advertised; space is allocated for the circ buff.
83 *------------------------------------------------------------------------*/
84
85struct gator_textcb_hdr *
86gator_textcb_Create(int a_maxEntriesStored, int a_maxCharsPerEntry)
87{ /*gator_textcb_Create */
88
89 static char rn[] = "gator_textcb_Create"; /*Routine name */
90 char *newBuff; /*Ptr to new text buffer */
91 struct gator_textcb_entry *newEntries; /*Ptr to new text entries */
92 struct gator_textcb_hdr *newHdr; /*Ptr to new text hdr */
93 int bytesToAllocate; /*Num bytes to allocate */
94 int numBuffBytes; /*Num bytes in text buffer */
95 int curr_ent_num; /*Current entry number */
96 struct gator_textcb_entry *curr_ent; /*Ptr to current entry */
97 char *curr_buff; /*Ptr to current buff pos */
98 int curr_inv; /*Current inversion idx */
99 char *blankLine; /*Ptr to blank line */
100 int i; /*Loop variable */
101
102 /*
103 * Start off by allocating the text buffer itself. Don't forget we
104 * need to allocate one more character per line, to make sure we can
105 * always null-terminate them. We also need to allocate the blank
106 * line buffer.
107 */
108 numBuffBytes = bytesToAllocate =
109 a_maxEntriesStored * (a_maxCharsPerEntry + 1);
110 if (gator_textcb_debug)
111 fprintf(stderr__stderrp, "[%s] Allocating %d bytes for the text buffer\n", rn,
112 bytesToAllocate);
113 newBuff = (char *)malloc(bytesToAllocate);
114 if (newBuff == NULL((void *)0)) {
115 fprintf(stderr__stderrp,
116 "[%s] Can't allocate %d bytes for text buffer; errno is %d\n",
117 rn, bytesToAllocate, errno(* __error()));
118 return ((struct gator_textcb_hdr *)0);
119 } else if (gator_textcb_debug)
120 fprintf(stderr__stderrp, "[%s] Text buffer allocated at %p\n", rn, newBuff);
121 blankLine = (char *)malloc(a_maxCharsPerEntry + 1);
122 if (blankLine == NULL((void *)0)) {
123 fprintf(stderr__stderrp,
124 "[%s] Can't allocate %d bytes for blank line buffer; errno is %d\n",
125 rn, a_maxCharsPerEntry + 1, errno(* __error()));
126 free(newBuff);
127 return ((struct gator_textcb_hdr *)0);
128 }
129
130 /*
131 * Next, allocate the entry array.
132 */
133 bytesToAllocate = a_maxEntriesStored * sizeof(struct gator_textcb_entry);
134 if (gator_textcb_debug)
135 fprintf(stderr__stderrp,
136 "[%s] Allocating %d bytes for the %d text entry array items\n",
137 rn, bytesToAllocate, a_maxEntriesStored);
138 newEntries = (struct gator_textcb_entry *)malloc(bytesToAllocate);
139 if (newEntries == (struct gator_textcb_entry *)0) {
140 fprintf(stderr__stderrp,
141 "[%s] Can't allocate %d bytes for the %d-member text entry array; errno is %d\n",
142 rn, bytesToAllocate, a_maxEntriesStored, errno(* __error()));
143 free(newBuff);
144 free(blankLine);
145 return ((struct gator_textcb_hdr *)0);
146 } else if (gator_textcb_debug)
147 fprintf(stderr__stderrp, "[%s] Text buffer entry array allocated at %p\n",
148 rn, newEntries);
149
150 /*
151 * Finish off by allocating the text circular buffer header.
152 */
153 bytesToAllocate = sizeof(struct gator_textcb_hdr);
154 if (gator_textcb_debug)
155 fprintf(stderr__stderrp,
156 "[%s] Allocating %d bytes for the text circular buffer header\n",
157 rn, bytesToAllocate);
158 newHdr = (struct gator_textcb_hdr *)malloc(bytesToAllocate);
159 if (newHdr == (struct gator_textcb_hdr *)0) {
160 fprintf(stderr__stderrp,
161 "[%s] Can't allocate %d bytes for text circular buffer header; errno is %d\n",
162 rn, bytesToAllocate, errno(* __error()));
163 free(newBuff);
164 free(blankLine);
165 free(newEntries);
166 return ((struct gator_textcb_hdr *)0);
167 } else if (gator_textcb_debug)
168 fprintf(stderr__stderrp,
169 "[%s] Text circular buffer header allocated at %p\n", rn,
170 newHdr);
171
172 /*
173 * Now, just initialize all the pieces and plug them in.
174 */
175 if (gator_textcb_debug)
176 fprintf(stderr__stderrp, "[%s] Zeroing %d bytes in text buffer at %p\n", rn,
177 numBuffBytes, newBuff);
178 memset(newBuff, 0, numBuffBytes);
179
180 if (gator_textcb_debug)
181 fprintf(stderr__stderrp, "[%s] Initializing blank line buffer at %p\n", rn,
182 blankLine);
183 for (i = 0; i < a_maxCharsPerEntry; i++)
184 *(blankLine + i) = ' ';
185 *(blankLine + a_maxCharsPerEntry) = '\0';
186
187 /*
188 * Initialize each buffer entry.
189 */
190 for (curr_ent_num = 0, curr_buff = newBuff, curr_ent = newEntries;
191 curr_ent_num < a_maxEntriesStored;
192 curr_ent++, curr_ent_num++, curr_buff += (a_maxCharsPerEntry + 1)) {
193 if (gator_textcb_debug)
194 fprintf(stderr__stderrp,
195 "[%s] Initializing buffer entry %d; its text buffer address is %p\n",
196 rn, curr_ent_num, curr_buff);
197 curr_ent->ID = 0;
198 curr_ent->highlight = 0;
199 curr_ent->numInversions = 0;
200 curr_ent->charsUsed = 0;
201 curr_ent->textp = curr_buff;
202 memcpy(curr_ent->textp, blankLine, a_maxCharsPerEntry + 1);
203 for (curr_inv = 0; curr_inv < GATOR_TEXTCB_MAXINVERSIONS10; curr_inv++)
204 curr_ent->inversion[curr_inv] = 0;
205
206 } /*Init each buffer entry */
207
208 if (gator_textcb_debug)
209 fprintf(stderr__stderrp, "[%s] Filling in circ buff header at %p\n", rn,
210 newHdr);
211 Lock_Init(&(newHdr->cbLock));
212 newHdr->maxEntriesStored = a_maxEntriesStored;
213 newHdr->maxCharsPerEntry = a_maxCharsPerEntry;
214 newHdr->currEnt = 0;
215 newHdr->currEntIdx = 0;
216 newHdr->oldestEnt = 0;
217 newHdr->oldestEntIdx = 0;
218 newHdr->entry = newEntries;
219 newHdr->blankLine = blankLine;
220
221 /*
222 * Finally, return the location of the new header.
223 */
224 return (newHdr);
225
226} /*gator_textcb_Create */
227
228/*------------------------------------------------------------------------
229 * bumpCB
230 *
231 * Description:
232 * Move down to the next circular buffer entry.
233 *
234 * Arguments:
235 * struct gator_textcb_hdr *a_cbhdr : Circ buff header to bump.
236 *
237 * Returns:
238 * Ptr to the newest current entry.
239 *
240 * Environment:
241 * Nothing interesting.
242 *
243 * Side Effects:
244 * As advertised.
245 *------------------------------------------------------------------------*/
246
247static struct gator_textcb_entry *
248bumpEntry(struct gator_textcb_hdr *a_cbhdr)
249
250{ /*bumpEntry */
251
252 static char rn[] = "bumpEntry"; /*Routine name */
253 struct gator_textcb_entry *curr_ent; /*Ptr to current entry */
254 int inv; /*Inversion number */
255
256 /*
257 * Bump the total number of writes, and don't forget to advance
258 * the oldest entry, if appropriate.
259 */
260 if (gator_textcb_debug)
261 fprintf(stderr__stderrp,
262 "[%s]: Bumping entry for circular buffer at %p; current values: currEnt=%d (idx %d), oldestEnt=%d (idx %d), maxEntriesStored=%d\n",
263 rn, a_cbhdr, a_cbhdr->currEnt, a_cbhdr->currEntIdx,
264 a_cbhdr->oldestEnt, a_cbhdr->oldestEntIdx,
265 a_cbhdr->maxEntriesStored);
266
267 a_cbhdr->currEnt++;
268 if (++(a_cbhdr->currEntIdx) >= a_cbhdr->maxEntriesStored)
269 a_cbhdr->currEntIdx = 0;
270 curr_ent = a_cbhdr->entry + a_cbhdr->currEntIdx;
271
272 if (gator_textcb_debug)
273 fprintf(stderr__stderrp, "[%s] Zeroing entry %d (idx %d) at %p\n", rn,
274 a_cbhdr->currEnt, a_cbhdr->currEntIdx, curr_ent);
275
276 curr_ent->ID = a_cbhdr->currEnt;
277 curr_ent->highlight = 0;
278 curr_ent->numInversions = 0;
279 curr_ent->charsUsed = 0;
280 /*
281 * Copy over a blank line into the one we're initializing. We
282 * copy over the trailing null, too.
283 */
284 memcpy(curr_ent->textp, a_cbhdr->blankLine,
285 a_cbhdr->maxCharsPerEntry + 1);
286 for (inv = 0; inv < GATOR_TEXTCB_MAXINVERSIONS10; inv++)
287 curr_ent->inversion[inv] = 0;
288
289 /*
290 * If we've already stated circulating in the buffer, remember to
291 * bump the oldest entry info too.
292 */
293 if (a_cbhdr->currEnt >= a_cbhdr->maxEntriesStored) {
294 if (gator_textcb_debug)
295 fprintf(stderr__stderrp,
296 "[%s]: Advancing oldest entry number & index; was entry %d, index %d, now ",
297 rn, a_cbhdr->oldestEnt, a_cbhdr->oldestEntIdx);
298 a_cbhdr->oldestEnt++;
299 if (++(a_cbhdr->oldestEntIdx) >= a_cbhdr->maxEntriesStored)
300 a_cbhdr->oldestEntIdx = 0;
301 if (gator_textcb_debug)
302 fprintf(stderr__stderrp, "entry %d, index %d\n", a_cbhdr->oldestEnt,
303 a_cbhdr->oldestEntIdx);
304 }
305
306 /*Bump oldest entry info */
307 /*
308 * Finally, return the address of the newest current entry.
309 */
310 return (curr_ent);
311
312} /*bumpEntry */
313
314/*------------------------------------------------------------------------
315 * gator_textcb_Write
316 *
317 * Description:
318 * Write the given string to the text circular buffer. Line
319 * breaks are caused either by overflowing the current text
320 * line or via explicit '\n's.
321 *
322 * Arguments:
323 * struct gator_textcb_hdr *a_cbhdr : Ptr to circ buff hdr.
324 * char *a_textToWrite : Ptr to text to insert.
325 * int a_numChars : Number of chars to write.
326 * int a_highlight : Use highlighting?
327 * int a_skip; : Force a skip to the next line?
328 *
329 * Returns:
330 * Zero if successful,
331 * Error value otherwise.
332 *
333 * Environment:
334 * Circular buffer is consistent upon entry, namely the first and
335 * last entry pointers are legal.
336 *
337 * Side Effects:
338 * As advertised.
339 *------------------------------------------------------------------------*/
340
341int
342gator_textcb_Write(struct gator_textcb_hdr *a_cbhdr, char *a_textToWrite,
343 int a_numChars, int a_highlight, int a_skip)
344{ /*gator_textcb_Write */
345
346 static char rn[] = "gator_textcb_Write"; /*Routine name */
347 struct gator_textcb_entry *curr_ent; /*Ptr to current text entry */
348 int curr_ent_idx; /*Index of current entry */
349 int max_chars; /*Max chars per entry */
350 int chars_to_copy; /*Num chars to copy in */
351 int effective_highlight; /*Tmp highlight value */
352 char *dest; /*Destination of char copy */
353
354 /*
355 * Make sure we haven't been passed a bogus buffer, and lock it
356 * before we start.
357 */
358 if (a_cbhdr == (struct gator_textcb_hdr *)0) {
359 fprintf(stderr__stderrp,
360 "[%s]: Null pointer passed in for circ buff header!! Aborting write operation.\n",
361 rn);
362 return (-1);
363 }
364 ObtainWriteLock(&(a_cbhdr->cbLock))do { ; if (!(&(a_cbhdr->cbLock))->excl_locked &&
!(&(a_cbhdr->cbLock))->readers_reading) (&(a_cbhdr
->cbLock)) -> excl_locked = 2; else Afs_Lock_Obtain(&
(a_cbhdr->cbLock), 2); ; } while (0)
;
365
366 curr_ent_idx = a_cbhdr->currEntIdx;
367 curr_ent = (a_cbhdr->entry) + curr_ent_idx;
368 max_chars = a_cbhdr->maxCharsPerEntry;
369 effective_highlight = curr_ent->highlight;
370 if (curr_ent->numInversions % 2)
371 effective_highlight = (effective_highlight ? 0 : 1);
372 if (gator_textcb_debug)
373 fprintf(stderr__stderrp,
374 "[%s]: Current entry: %d (at index %d, keeping %d max), effective highlight: %d, located at %p\n",
375 rn, a_cbhdr->currEnt, curr_ent_idx, a_cbhdr->maxEntriesStored,
376 effective_highlight, curr_ent);
377
378 while (a_numChars > 0) {
379 /*
380 * There are still characters to stuff into our circular buffer.
381 */
382 if (gator_textcb_debug)
383 fprintf(stderr__stderrp,
384 "[%s]: Top of write loop: %d char(s) left to write.\n",
385 rn, a_numChars);
386
387 if (curr_ent->charsUsed >= max_chars) {
388 /*
389 * Bump the entry in the given circular buffer.
390 */
391 if (gator_textcb_debug)
392 fprintf(stderr__stderrp,
393 "[%s]: Entry %d at index %d full, advancing to next one.\n",
394 rn, a_cbhdr->currEnt, curr_ent_idx);
395 curr_ent = bumpEntry(a_cbhdr);
396 curr_ent_idx = a_cbhdr->currEntIdx;
397 if (gator_textcb_debug)
398 fprintf(stderr__stderrp,
399 "[%s] New CB entry info: currEnt=%d (idx %d), oldestEnt=%d (idx %d), curr entry ptr is %p\n",
400 rn, a_cbhdr->currEnt, a_cbhdr->currEntIdx,
401 a_cbhdr->oldestEnt, a_cbhdr->oldestEntIdx, curr_ent);
402 }
403
404 /*Bump current entry */
405 /*
406 * At this point, the current entry has room for at least one more
407 * character, and we have at least one more character to write.
408 * Insert as much from the user text as possible.
409 */
410 chars_to_copy = max_chars - curr_ent->charsUsed;
411 if (a_numChars < chars_to_copy)
412 chars_to_copy = a_numChars;
413 dest = curr_ent->textp + curr_ent->charsUsed;
414 if (gator_textcb_debug)
415 fprintf(stderr__stderrp,
416 "[%s]: Copying %d char(s) into current entry at %p (entry buffer starts at %p)\n",
417 rn, chars_to_copy, dest, curr_ent->textp);
418
419 /*
420 * Handle highlighting and inversions.
421 */
422 if (curr_ent->charsUsed == 0) {
423 /*
424 * No chars yet, so this sets the highlight field.
425 */
426 effective_highlight = curr_ent->highlight = a_highlight;
427 } else if (effective_highlight != a_highlight) {
428 /*
429 * We need a new inversion, if there's room.
430 */
431 if (gator_textcb_debug)
432 fprintf(stderr__stderrp,
433 "[%s]: Highlight mismatch, recording inversion at char loc %d\n",
434 rn, curr_ent->charsUsed);
435 if (curr_ent->numInversions < GATOR_TEXTCB_MAXINVERSIONS10) {
436 effective_highlight = a_highlight;
437 curr_ent->inversion[curr_ent->numInversions] =
438 curr_ent->charsUsed;
439 curr_ent->numInversions++;
440 } else if (gator_textcb_debug)
441 fprintf(stderr__stderrp, "[%s]: Out of inversions!!\n", rn);
442 }
443
444 /*Handle inversion */
445 /*
446 * Move the string chunk into its place in the buffer, bump the
447 * number of chars used in the current entry.
448 */
449 strncpy(dest, a_textToWrite, chars_to_copy);
450 curr_ent->charsUsed += chars_to_copy;
451 a_textToWrite += chars_to_copy;
452 a_numChars -= chars_to_copy;
453
454 } /*while (a_numChars > 0) */
455
456 /*
457 * All characters have been copied in. Handle the case where we've
458 * been asked to skip to the next entry, even if there's still room
459 * in the current one.
460 */
461 if (a_skip) {
462 if (gator_textcb_debug)
463 fprintf(stderr__stderrp, "[%s] Handling request to skip to next entry\n",
464 rn);
465 if (curr_ent->charsUsed > 0)
466 curr_ent = bumpEntry(a_cbhdr);
Value stored to 'curr_ent' is never read
467 else if (gator_textcb_debug)
468 fprintf(stderr__stderrp,
469 "[%s] Not skipping, we're already on a fresh entry\n",
470 rn);
471 }
472
473 /*Skip to the next entry */
474 /*
475 * We can now unlock the CB and return successfully.
476 */
477 ReleaseWriteLock(&(a_cbhdr->cbLock))do { ; (&(a_cbhdr->cbLock))->excl_locked &= ~2;
if ((&(a_cbhdr->cbLock))->wait_states) Afs_Lock_ReleaseR
(&(a_cbhdr->cbLock)); ; } while (0)
;
478 return (0);
479
480} /*gator_textcb_Write */
481
482/*------------------------------------------------------------------------
483 * gator_textcb_BlankLine
484 *
485 * Description:
486 * Write out some number of blank lines to the given circular
487 * buffer.
488 *
489 * Arguments:
490 * struct gator_textcb_hdr *a_cbhdr : Ptr to circ buff hdr.
491 * int *a_numBlanks : Num. blank lines to write.
492 *
493 * Returns:
494 * Zero if successful,
495 * Error value otherwise.
496 *
497 * Environment:
498 * Circular buffer is consistent upon entry, namely the first and
499 * last entry pointers are legal.
500 *
501 * Side Effects:
502 * As advertised.
503 *------------------------------------------------------------------------*/
504
505int
506gator_textcb_BlankLine(struct gator_textcb_hdr *a_cbhdr,
507 int a_numBlanks)
508{ /*gator_textcb_BlankLine */
509
510 static char rn[] = "gator_textcb_BlankLine"; /*Routine name */
511
512 if (gator_textcb_debug)
513 fprintf(stderr__stderrp, "[%s] Putting out %d blank lines to the CB at %p\n",
514 rn, a_numBlanks, a_cbhdr);
515
516 if (a_cbhdr == (struct gator_textcb_hdr *)0) {
517 if (gator_textcb_debug)
518 fprintf(stderr__stderrp, "[%s] Null pointer passed for CB hdr!!\n", rn);
519 return (-1);
520 }
521
522 while (a_numBlanks > 0) {
523 /*
524 * The bumpEntry routine returns a struct gator_textcb_entry
525 * pointer, but we don't need it here, so we don't assign it.
526 */
527 bumpEntry(a_cbhdr);
528 a_numBlanks--;
529 }
530
531 /*
532 * Return happily and successfully.
533 */
534 return (0);
535
536} /*gator_textcb_Write */
537
538/*------------------------------------------------------------------------
539 * gator_textcb_Delete
540 *
541 * Description:
542 * Delete the storage used by the given circular buffer, including
543 * the header itself.
544 *
545 * Arguments:
546 * struct gator_textcb_hdr *a_cbhdr : Ptr to the header of the
547 * circ buffer to reap.
548 *
549 * Returns:
550 * Zero if successful,
551 * Error value otherwise.
552 *
553 * Environment:
554 * We write-lock the buffer before deleting it, which is slightly
555 * silly, since it will stop existing after we're done. At least
556 * we'll make sure nobody is actively writing to it while it's
557 * being deleted.
558 *
559 * Side Effects:
560 * As advertised.
561 *------------------------------------------------------------------------*/
562
563int
564gator_textcb_Delete(struct gator_textcb_hdr *a_cbhdr)
565{ /*gator_textcb_Delete */
566
567 static char rn[] = "gator_textcb_Delete"; /*Routine name */
568
569 if (gator_textcb_debug)
570 fprintf(stderr__stderrp, "[%s]: Deleting text circular buffer at %p\n", rn,
571 a_cbhdr);
572 ObtainWriteLock(&(a_cbhdr->cbLock))do { ; if (!(&(a_cbhdr->cbLock))->excl_locked &&
!(&(a_cbhdr->cbLock))->readers_reading) (&(a_cbhdr
->cbLock)) -> excl_locked = 2; else Afs_Lock_Obtain(&
(a_cbhdr->cbLock), 2); ; } while (0)
;
573
574 /*
575 * The beginning of the text buffer itself is pointed to by the
576 * first text entry.
577 */
578 if (gator_textcb_debug)
579 fprintf(stderr__stderrp,
580 "[%s]: Freeing text buffer proper at %p (%d bytes)\n", rn,
581 a_cbhdr->entry[0].textp,
582 (a_cbhdr->maxEntriesStored * a_cbhdr->maxCharsPerEntry));
583 free(a_cbhdr->entry[0].textp);
584 a_cbhdr->entry[0].textp = NULL((void *)0);
585
586 if (gator_textcb_debug)
587 fprintf(stderr__stderrp, "[%s]: Freeing text entry array at %p (%" AFS_SIZET_FMT"zu" " bytes)\n",
588 rn, a_cbhdr->entry,
589 (a_cbhdr->maxEntriesStored *
590 sizeof(struct gator_textcb_entry)));
591 free(a_cbhdr->entry);
592 a_cbhdr->entry = (struct gator_textcb_entry *)0;
593 free(a_cbhdr->blankLine);
594 a_cbhdr->blankLine = NULL((void *)0);
595
596 /*
597 * Release the write lock on it, then free the header itself.
598 */
599 ReleaseWriteLock(&(a_cbhdr->cbLock))do { ; (&(a_cbhdr->cbLock))->excl_locked &= ~2;
if ((&(a_cbhdr->cbLock))->wait_states) Afs_Lock_ReleaseR
(&(a_cbhdr->cbLock)); ; } while (0)
;
600 if (gator_textcb_debug)
601 fprintf(stderr__stderrp, "[%s] Freeing cicular buffer header at %p\n", rn,
602 a_cbhdr);
603 free(a_cbhdr);
604 return (0);
605
606} /*gator_textcb_Delete */