improve behaviour under VPC, fixes from nicolas tittley.
[minix.git] / commands / elle / sberr.c
blobc707532b6e72e003426901c273b5d4c8eb7564bb
1 /* SB - Copyright 1982 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author. In all cases
5 * the source code and any modifications thereto must remain
6 * available to any user.
8 * This is part of the SB library package.
9 * Any software using the SB library must likewise be made
10 * quasi-public, with freely available sources.
13 #define PRINT /* Include printout stuff */
15 #include "sb.h"
16 #include <stdio.h>
18 extern struct smblk *sbm_nfl;
19 extern struct smblk *sbm_list;
20 extern struct sdblk *sbx_nfl;
22 #ifdef PRINT
23 #define PRF(stmt) {if(p) stmt;}
24 #define PRFBUG(str,stmt) {if(p) stmt;else return(str);}
25 #define PRFBAD(str,stmt) {if(p) stmt; return(str);}
26 #else
27 #define PRF(stmt) ;
28 #define PRFBUG(str,stmt) return(str);
29 #define PRFBAD(str,stmt) return(str);
30 #endif
32 #ifndef NPTRS
33 #define NPTRS (1000) /* Catch loops of period less than this. */
34 #endif
36 int sbe_dec = 0; /* Set nonzero to use decimal printout */
38 struct ptab {
39 int pt_pflag; /* Printflag value */
40 char *pt_err; /* Error string return */
41 int pt_xerr; /* Error index return */
42 int pt_hidx; /* Highest freelist entry */
43 int pt_nsto; /* # entries stored in table */
44 int pt_cnt; /* # of entry store attempts */
45 struct smblk *pt_tab[NPTRS];
48 _PROTOTYPE( char *sbe_sdtab, (struct ptab *pt, int p, int phys) );
49 _PROTOTYPE( char *sbe_schk, (struct sdblk *sd, struct ptab *pt) );
50 _PROTOTYPE( int sbe_tbent, (struct ptab *pt, struct smblk *sm) );
52 #define PTF_PRF 01 /* Do printout stuff */
53 #define PTF_OVFERR 02 /* Complain if table overflows */
54 #define PTF_SDPHYS 04 /* Follow SD phys links (else logical links) */
56 struct flgt {
57 int flg_bit;
58 int flg_chr;
61 _PROTOTYPE( char *sbe_fstr, (int flags, struct flgt *fp) );
63 char *sbe_mvfy(), *sbe_mfl(), *sbe_mlst(); /* SBM */
64 char *sbe_sbvfy(), *sbe_sbs(); /* SBBUF */
65 char *sbe_svfy(), *sbe_sdlist(), *sbe_sdtab(), *sbe_schk(); /* SD */
66 char *sbe_fstr(); /* Misc utility */
69 /* SBE_MEM() - Print out memory usage list
71 sbe_mem()
73 printf("\nMemory Usage:\n");
74 printf("\tsbm_nfl : %6o\n",sbm_nfl);
75 printf("\tsbm_list: %6o\n",sbm_list);
76 printf("\tsmblk nodes are %o bytes long.\n",sizeof (struct smblk));
78 sbe_mlst(1); /* Scan mem list, printing stuff. */
81 /* SBE_MVFY() - Verify memory allocation structures
82 * Returns error message (0 if no errors found).
84 char *
85 sbe_mvfy()
86 { register char *res;
88 if((res = sbe_mfl(0))
89 || (res = sbe_mlst(0)))
90 return(res);
91 return(0);
94 /* SBM Debugging Routines */
96 struct flgt smflgtab[] = {
97 SM_USE, 'U',
98 SM_NXM, 'N',
99 SM_EXT, 'E',
100 SM_MNODS,'M',
101 SM_DNODS,'D',
105 static char smfhelp[] = "U-Used, N-NXM, E-External, M-SMnodes, D-SDnodes";
106 static char smhdline[] = "\
107 SM: back smaddr smlen smuse smflags";
109 /* SBE_MFL(printflag) - Verify/Print memory freelist
110 * Returns error message (0 if no errors found).
112 char *
113 sbe_mfl(p)
114 int p;
115 { register struct smblk *sm;
116 register int i;
117 struct ptab smtab; /* For loop detection */
119 PRF(printf("Tracing SM node freelist --\n"))
120 PRF(printf(" Maximum loop detection size is %d.", NPTRS))
121 if((sm = sbm_nfl) == 0)
122 { PRF(printf("\n\tNo list.\n"))
123 return(0); /* Null freelist is ok */
125 smtab.pt_pflag = p ? PTF_PRF : 0;
126 smtab.pt_nsto = smtab.pt_cnt = 0;
127 i = 0; /* Print 8 addrs/line */
128 for(; sm; sm = sm->smforw)
130 PRF(printf("%s%7o->", (i==0 ? "\n " : ""), sm))
131 if(++i >= 8) i = 0;
132 if(sbe_tbent(&smtab, sm) < 0) /* If hit loop, stop */
133 PRFBAD("SM freelist loop",
134 printf("\nLOOP - %o seen as node %d!!\n",
135 sm, smtab.pt_xerr))
136 if(sm->smflags)
137 { PRF((i = 0, printf("\nFreelist node has flags:\n")))
138 PRFBUG("Free SM flagged", sbe_smp(sm, 0))
141 PRF(printf("\nEnd - %d nodes on SM freelist.\n", smtab.pt_cnt))
142 return(0);
145 /* SBE_MLST(printflag) - Verify/Print allocated memory list.
146 * Returns error message (0 if no errors found).
148 char *
149 sbe_mlst(p)
150 int p;
151 { register struct smblk *sm, *smf, *smb;
152 char *nextaddr;
153 int i;
154 struct ptab smtab; /* For loop detection */
156 PRF(printf("Tracing mem list -- \n"))
157 if((sm = sbm_list) == 0)
158 { PRF(printf("\tNo list?!\n"))
159 if(sbm_nfl) /* Ensure rest are 0 too */
160 return("No mem list?!!");
161 return(0);
164 smtab.pt_pflag = p;
165 smtab.pt_cnt = smtab.pt_nsto = 0;
166 smb = 0;
167 PRF(printf(" Flags: %s\n%s\n", smfhelp, smhdline))
168 for(; sm; sm = smf)
169 { PRF(printf(" %6o: ",sm))
170 if(sbe_tbent(&smtab, sm) < 0)
171 PRFBAD("Loop in mem list!!",
172 printf("LOOP - seen as node %d!!\n", smtab.pt_xerr))
174 if(sm->smback == smb)
175 PRF(printf("^ ")) /* Back ptr OK */
177 else PRFBUG("Bad back ptr!",
178 printf("%6o BAD Backptr!!\n\t ",sm->smback))
180 if((sm->smflags&0377)!= SM_NID)
181 PRFBUG("SM: bad node ID",
182 printf("BAD - no node ID!\n\t "))
183 PRF(printf((sm->smflags&SM_USE) ? " " : "FREE "))
184 if(sm->smlen == 0)
185 PRFBUG("SM: len 0",
186 printf("Zero-length area!"))
187 if((sm->smflags&SM_USE)==0
188 && rndrem(sm->smaddr - sbm_lowaddr))
189 PRFBUG("Bad free-mem block",
190 printf("Bad free-mem block"))
191 PRF(sbe_smp(sm, 1)) /* Print out rest of info */
193 if(nextaddr != sm->smaddr
194 && smtab.pt_cnt != 1) /* 1st time needs init */
195 { PRFBUG("Alignment error!",
196 printf("\t BAD!! %6o expected; ",nextaddr))
197 #if !(MINIX)
198 PRF((i = sm->smaddr - nextaddr) > 0
199 ? printf("%d skipped.\n",i)
200 : printf("%d overlapped.\n",-i))
201 #endif
203 nextaddr = sm->smaddr + sm->smlen;
204 smf = sm->smforw;
205 smb = sm; /* Save ptr to back */
207 PRF(printf("End = %6o\n",nextaddr))
208 return(0);
211 #ifdef PRINT
212 sbe_smp(sm,type)
213 register struct smblk *sm;
214 int type;
216 if(type==0)
217 printf(" %6o: %s ", sm,
218 ((sm->smflags&SM_USE) ? " " : "FREE"));
219 printf("%6o: ", sm->smaddr);
220 printf((sbe_dec ? "%5d. %5d." : "%6o %6o"), sm->smlen, sm->smuse);
221 printf(" %7o = %s\n", sm->smflags, sbe_fstr(sm->smflags, smflgtab));
223 #endif /*PRINT*/
225 /* SD (SBSTR) debugging routines */
227 struct flgt sdflgtab[] = {
228 SD_LOCK, 'L',
229 SD_LCK2, 'T',
230 SD_MOD, '*',
234 static char sdfhelp[] = "\
235 <f> flags: *-MOD (disk outofdate), L-LOCK, T-LCK2 (temp)";
236 static char sdhdline[] = "\
237 <f> SD: slforw slback sdflgs sdforw sdback sdmem sdfile sdaddr sdlen";
240 /* SBE_SFL(printflag) - Verify/Print SD freelist
241 * Returns error message (0 if no errors found).
243 char *
244 sbe_sfl(p)
245 int p;
246 { register struct sdblk *sd;
247 register int i;
248 struct ptab sdtab; /* For loop detection */
250 PRF(printf("Tracing SDBLK node freelist --\n"))
251 PRF(printf(" Maximum loop detection size is %d.", NPTRS))
252 if((sd = sbx_nfl) == 0)
253 { PRF(printf("\n\tNo list.\n"))
254 return(0); /* Null freelist is ok */
256 sdtab.pt_pflag = p ? PTF_PRF : 0;
257 sdtab.pt_nsto = sdtab.pt_cnt = 0;
258 i = 0; /* Print 8 addrs/line */
259 for(; sd; sd = sd->slforw)
261 PRF(printf("%s%7o->", (i==0 ? "\n " : ""), sd))
262 if(++i >= 8) i = 0;
263 if(sbe_tbent(&sdtab, sd) < 0) /* If hit loop, stop */
264 PRFBAD("SD freelist loop",
265 printf("\nLOOP - %o seen as node %d!!",
266 sd, sdtab.pt_xerr))
267 if(sd->sdflags)
268 { PRF((i = 0, printf("\nFreelist node has flags:\n")))
269 PRFBUG("Free SD flagged", sbe_psd(sd))
272 PRF(printf("\nEnd - %d nodes on SD freelist.\n", sdtab.pt_cnt))
273 return(0);
278 /* SBE_SDS() - Print out all sdblk data stuff
280 sbe_sds()
281 { int sbe_psd();
283 printf("Printout of all in-use SDBLKs:\n");
284 printf(" %s\n", sdfhelp);
285 printf("%s\n", sdhdline);
286 sbm_nfor(SM_DNODS,sizeof(struct sdblk),sbe_psd,0);
287 printf("\n");
290 /* SBE_PSD - Auxiliary for invocation by SBE_SDS above. */
291 sbe_psd(sd)
292 register struct sdblk *sd;
293 { register int flags;
295 flags = sd->sdflags;
296 printf("%c%c%c",
297 ((flags&SD_MOD) ? '*' : ' '),
298 ((flags&SD_LOCK) ? 'L' : ' '),
299 ((flags&SD_LCK2) ? 'T' : ' '));
301 printf(" %7o: %6o %6o %6o %6o %6o %6o %6o %7lo %5ld.\n", sd,
302 sd->slforw, sd->slback, sd->sdflags,
303 sd->sdforw, sd->sdback, sd->sdmem,
304 sd->sdfile, sd->sdaddr, sd->sdlen);
305 return(0);
308 /* SBE_SVFY() - Verify all SD blocks
309 * Returns error message (0 if no errors found).
311 char *
312 sbe_svfy()
313 { register char *res;
314 return((res = sbe_sdlist(0,0)) ? res : sbe_sdlist(0,1));
317 /* SBE_SDLIST(printflag, physflag) - Verify/Print all SD blocks.
318 * Show logical lists if physflag 0
319 * Show physical lists otherwise
320 * Returns error message (0 if no errors found).
322 char *
323 sbe_sdlist(p,phys)
324 int p, phys;
325 { register char *res;
326 struct ptab sdtab; /* The SDLIST table to use */
328 /* First put freelist in table, then scan for all
329 * SD nodes. Each active node (not in table) gets
330 * its entire list traced forward/backward and added to table.
332 if(res = sbe_sdtab(&sdtab, p, phys)) /* Set up freelist table */
333 return(res);
335 /* Freelist entered in table, now scan all SD's */
336 res = (char *)sbm_nfor(SM_DNODS,sizeof(struct sdblk),
337 sbe_schk, &sdtab);
339 PRF(printf("\n"))
340 return(res);
343 /* SBE_SDTAB(tableptr, printflag, physflag) - Auxiliary for SBE_SDLIST.
344 * Stuffs all freelist SDBLK addresses in table for dup detection.
345 * Returns error message (0 if no errors found).
347 char *
348 sbe_sdtab(pt, p, phys)
349 register struct ptab *pt;
350 int p, phys;
351 { register struct sdblk *sd;
352 register int res;
354 pt->pt_pflag = (p ? PTF_PRF : 0) | (phys ? PTF_SDPHYS : 0)
355 | PTF_OVFERR;
356 pt->pt_cnt = pt->pt_nsto = 0; /* Initialize */
358 /* Stick freelist in table */
359 for(sd = sbx_nfl; sd; sd = sd->slforw)
360 { if(sbe_tbent(pt, sd) < 0)
361 { if(pt->pt_xerr < 0)
362 PRFBAD("SD freelist too long",
363 printf("SD freelist too long (%d)\n",
364 NPTRS))
365 PRFBAD("SD freelist loop",
366 printf("SD freelist loop at %o\n", pt->pt_xerr))
369 if(sd->sdflags)
371 PRF(printf("Bad free SD, non-zero flag:\n"))
372 PRFBUG("Free SD flagged", sbe_psd(sd))
375 pt->pt_hidx = pt->pt_nsto; /* Set idx of 1st non-FL entry */
376 return(0);
379 /* SBE_SCHK(SDptr, tableptr) - Auxiliary for SBE_SDLIST.
380 * If SD not already in table, verifies or prints
381 * the complete physical or logical list it's on, and enters all
382 * of its SDs into table (to prevent doing it again).
383 * Returns 0 if no errors, else error string.
384 ** There is a problem when the table overflows. The tbent routine
385 ** wants to add it (wrapping around at bottom) in that case, because
386 ** that still helps detect loops. But this routine wants to reset
387 ** the table back (after scanning to head of list) and once it starts
388 ** scanning forward again it will fail, because some of the SDs are
389 ** still in the table due to the wraparound! Thus PTF_OVFERR is always
390 ** set, in order to at least give the right error message.
392 char *
393 sbe_schk(sd, pt)
394 register struct sdblk *sd;
395 struct ptab *pt;
396 { register struct sdblk *sdx;
397 register struct smblk *sm;
398 struct sbfile *savfile;
399 chroff lastaddr;
400 int p, res, savidx, phys;
402 phys = pt->pt_pflag&PTF_SDPHYS; /* Set up physflag */
403 if(phys && (sd->sdfile == 0)) /* Ignore non-phys stuff if phys */
404 return(0);
405 p = pt->pt_pflag&PTF_PRF; /* Set up printflag */
406 savidx = pt->pt_nsto; /* Remember initial extent of table */
408 if(sbe_tbent(pt, sd) < 0)
409 { if(pt->pt_xerr >= 0) /* OK if already in table */
410 return(0);
411 PRFBAD("Too many SDs",
412 printf("Too many SDs for table (%d)\n", NPTRS))
415 /* Now search backward for start of list */
416 while(sdx = (phys ? sd->sdback : sd->slback))
417 if(sbe_tbent(pt,sdx) >= 0)
418 sd = sdx;
419 else break;
420 if(sdx)
421 { if(pt->pt_xerr < 0) /* Table error? */
422 PRFBAD("Too many SDs",
423 printf("Too many SDs for table (%d)\n",NPTRS))
424 PRF(printf("Backlist loop!! Dup'd node:%s\n",
425 (pt->pt_xerr < pt->pt_hidx) ?
426 "(on freelist!)" : "" ))
427 PRFBUG((phys ? "Phys SD loop" : "SD loop"), sbe_psd(sdx))
429 /* Reset table to flush nodes backed over */
430 pt->pt_cnt = pt->pt_nsto = savidx;
432 /* SD now points to start of list. Begin stepping thru list... */
433 PRF(printf("---- %sList started: ", (phys ? "Phys " : "")))
434 if(phys)
435 { savfile = sd->sdfile;
436 PRF(printf(" SF: %o, fd= %d, ln= %ld\n",
437 savfile,savfile->sffd,savfile->sflen))
438 if(savfile->sfptr1 != sd)
439 PRFBUG("SFPTR1 bad",
440 printf(" BAD!! Sfptr1 %o doesn't match SD %o!!\n",
441 savfile->sfptr1, sd))
442 lastaddr = 0;
444 else PRF(printf("\n"))
446 PRF(printf("%s\n", sdhdline))
447 for(sdx = 0; sd; (sdx = sd, sd = (phys ? sd->sdforw : sd->slforw)))
449 PRF(sbe_psd(sd)) /* Print it out */
450 if(sdx != (phys ? sd->sdback : sd->slback))
451 { if(phys)
452 PRFBUG("PSD bad sdback",printf("\tBad phys backptr\n"))
453 else
454 PRFBUG("SD bad slback",printf("\tBad backptr\n"))
457 if((sd->sdflags&0377) != SD_NID)
458 PRFBUG("Bad SD node ID", printf("\tBad node ID!\n"))
461 if(sd->sdfile && (sd->sdlen < 0 || sd->sdaddr < 0))
462 PRFBUG("SD: neg len/addr",
463 printf("\tNeg disk len/addr\n"))
464 if(phys) goto dophys;
466 /* Do special stuff for logical list */
467 if(sm = sd->sdmem)
468 { if((sm->smflags&0377) != SM_NID)
469 PRFBUG("SD: bad SM",
470 printf("\nBad SMBLK ptr\n"))
471 if((sd->sdflags&SD_MOD)==0
472 && sd->sdlen != sm->smuse)
473 PRFBUG("SD != SM",
474 printf("\tBad SMBLK? Len conflict\n"))
475 if(sm->smlen < sm->smuse)
476 PRFBUG("SD: SM len < use",
477 printf("\tBad SMBLK, len < use\n"))
479 goto doboth; /* Skip phys stuff */
481 /* Do special stuff for phys list */
482 dophys: if(sd->sdfile != savfile)
483 PRFBUG("SD: bad sdfile",
484 printf("\tBad sdfile ptr! Shd be %o\n",
485 savfile))
486 if(sd->sdaddr < lastaddr)
487 PRFBUG("SD addr out of order",
488 printf("\tBad disk addr, not in order!\n"))
489 lastaddr = sd->sdaddr;
490 /* Done with special phys stuff */
492 doboth: if(sbe_tbent(pt, sd) < 0)
493 { if(pt->pt_xerr < 0)
494 PRFBAD("Too many SDs",
495 printf("Too many SDs for table (%d)\n",NPTRS))
497 PRFBUG("SD loop",
498 printf("\tLOOP!! This SD already seen%s.\n",
499 (pt->pt_xerr < pt->pt_hidx) ?
500 " (on freelist!)" : "" ))
501 break;
504 PRF(printf("-----------\n"))
505 return(0);
508 /* SBE_DSK(SFptr) - Print out disk usage list for specific file
511 sbe_dsk(sfp)
512 SBFILE *sfp;
514 printf("SBFILE printout not coded: %o\n",sfp);
517 /* SBBUF structure debugging routines */
519 struct flgt sbflgtab[] = {
520 SB_OVW, 'O',
521 SB_WRIT,'W',
524 static char sbfhelp[] = "O-Overwrite, W-Write";
526 /* SBE_SBVFY(SBptr) - Verify a SB-string.
527 * Returns error message (0 if no errors found).
529 char *
530 sbe_sbvfy(sbp)
531 SBBUF *sbp;
532 { return(sbe_sbs(sbp,0));
535 /* SBE_SBS(SBptr, printflag) - Verify/Print SBSTR data stuff
536 * Returns error message (0 if no errors found).
538 char *
539 sbe_sbs(sbp,p)
540 SBBUF *sbp;
541 int p;
542 { register SBBUF *sb;
543 register struct smblk *sm;
544 register struct sdblk *sd;
546 sb = sbp;
547 PRF(printf("SBSTR %o: ",sb))
548 if(sb == 0)
549 PRFBUG(0,printf("Zero pointer???\n"))
551 /* First print out cryptic summary in case pointers bomb
552 * out farther on. */
553 PRF(printf(" (io,cur,r,w,f,.,+ = %o,%o,%d,%d,%o,%lo,%lo)\n",
554 sb->sbiop, sb->sbcur, sb->sbrleft, sb->sbwleft,
555 sb->sbflags, sb->sbdot, sb->sboff))
557 PRF(printf(" sbflags %5o = %s (%s)\n",
558 sb->sbflags, sbe_fstr(sb->sbflags,sbflgtab),
559 sbfhelp))
561 if(sd = sb->sbcur) /* Okay, now try getting pointers */
562 sm = sd->sdmem;
563 else sm = 0;
565 PRF(printf(" sbcur %6o",sd))
566 if(sd)
568 PRF(printf("\n %s\n ", sdhdline))
569 PRF(sbe_psd(sd))
571 if((sd->sdflags&0377) != SD_NID)
572 PRFBUG("SBCUR not SD?",printf(" BAD SDBLK ID!! \n"))
573 if(sm)
575 PRF(printf(" %s\n ", smhdline))
576 PRF(sbe_smp(sm,0))
577 if((sm->smflags&0377) != SM_NID)
578 PRFBUG("SBCUR has bad SM",
579 printf(" BAD SMBLK ID!!\n"))
584 PRF(printf(" sbiop %6o",sb->sbiop))
585 if(sb->sbiop)
586 { if(!sm || sb->sbiop < sm->smaddr
587 || sb->sbiop > (sm->smaddr + sm->smlen))
588 PRFBUG("Bad SBIOP", printf(" BAD"))
590 else if(sb->sbrleft > 0 || sb->sbwleft > 0)
591 PRFBUG("Bad SBIOP/cnts", printf(" BAD"))
592 PRF(printf("\n"))
594 PRF(printf(" sbrleft %5o = %5d.",sb->sbrleft, sb->sbrleft))
595 if(sb->sbrleft
596 && ( !sm
597 || sb->sbwleft
598 || (sb->sbflags&SB_WRIT)
599 || (sb->sbrleft != (sm->smuse - (sb->sbiop - sm->smaddr)))
601 PRFBUG("Bad sbrleft", printf(" BAD"))
602 PRF(printf("\n"))
604 PRF(printf(" sbwleft %5o = %5d.", sb->sbwleft, sb->sbwleft))
605 if(sb->sbwleft
606 && ( !sm
607 || (sb->sbflags&SB_WRIT) == 0
608 || (sb->sbwleft > (sm->smlen - (sb->sbiop - sm->smaddr)))
610 PRFBUG("Bad sbwleft", printf(" BAD"))
611 PRF(printf("\n"))
613 PRF(printf(" sbdot %7lo = %7ld.", sb->sbdot, sb->sbdot))
614 if(sb->sbdot < 0)
615 PRFBUG("Bad sbdot", printf(" BAD"))
617 PRF(printf("\n sboff %7lo = %7ld.\n", sb->sboff, sb->sboff))
618 PRF(printf(" I/O ptr loc: %ld.\n\n", sb_tell(sb)))
620 return(0);
623 /* SBE_TBENT() - Auxiliary to add and check entries to a pointer table.
624 * Note we assume here that smblk ptrs are used, although sdblks
625 * can also be hacked. This wins as long as the two kinds of ptrs
626 * are basically identical (saves horrible casting problems).
627 * Returns index # if successful (between 0 and NPTRS-1 inclusive).
628 * Otherwise an error (-1), with relevant info in pt_xerr:
629 * -1 if out of room and flag set making it an error
630 * 0-n if entry already existed.
632 sbe_tbent(pt, sm)
633 register struct ptab *pt;
634 struct smblk *sm;
635 { register struct smblk **smt;
636 register int i;
637 int p;
639 p = pt->pt_pflag&PTF_PRF; /* Set up print flag */
640 smt = &(pt->pt_tab[0]);
641 if(i = pt->pt_nsto)
642 { do {
643 if(sm == *smt++)
644 { pt->pt_xerr = pt->pt_nsto - i;
645 return(-1);
647 } while(--i);
648 --smt;
651 i = pt->pt_cnt++;
652 if(++(pt->pt_nsto) > NPTRS)
653 { if(pt->pt_pflag&PTF_OVFERR)
654 { pt->pt_err = "Ptrtab overflow";
655 pt->pt_xerr = -1;
656 return(-1);
658 pt->pt_nsto = NPTRS;
659 i %= NPTRS;
661 pt->pt_tab[i] = sm;
662 return(i);
665 /* SBE_FSTR(flags, flagtab) - Auxiliary to convert flag word to a string
666 * and return pointer to it. Handy for printfs.
668 char *
669 sbe_fstr(flags, fp)
670 register int flags;
671 register struct flgt *fp;
672 { static char retstr[17]; /* Max of 16 flags */
673 register char *cp;
674 cp = retstr;
675 for(; fp->flg_bit; ++fp)
676 *cp++ = (fp->flg_bit&flags) ? fp->flg_chr : ' ';
677 *cp = 0;
678 return(retstr);