comparison distress.c @ 3:5a977ccbc7a9 default tip

Empty changelog
author darius
date Sat, 06 Dec 1997 05:41:29 +0000
parents
children
comparison
equal deleted inserted replaced
2:fba0b6e6cdc7 3:5a977ccbc7a9
1 /* $Id: distress.c,v 1.1.1.1 1997/12/06 05:41:29 darius Exp $ */
2
3 /*
4 * distress.c
5 */
6 #include "copyright.h"
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <signal.h>
11 #include <ctype.h>
12 #include <string.h>
13 #ifndef SERVER
14 #include "Wlib.h"
15 #endif
16 #include "defs.h"
17 #include "struct.h"
18 #include "data.h"
19 #include "gameconf.h"
20 #include "proto.h"
21
22 /* #$!@$#% length of address field of messages */
23 #define ADDRLEN 10
24 #define MAXMACLEN 256
25 #define MZERO bzero
26
27
28 /*
29 * The two in-line defs that follow enable us to avoid calling strcat over
30 * and over again.
31 */
32 char *pappend;
33 #define APPEND(ptr,str) \
34 pappend = str; \
35 while(*pappend) \
36 *ptr++ = *pappend++;
37
38 #define APPEND_CAP(ptr,cap,str) \
39 pappend = str; \
40 while(*pappend) \
41 { \
42 *ptr++ = (cap ? toupper(*pappend) : *pappend); \
43 pappend++; \
44 }
45
46 /*
47 * This is a hacked version from the K&R book. Basically it puts <n> into
48 * <s> in reverse and then reverses the string...
49 * MH. 10-18-93
50 */
51 int
52 itoa2(n, s)
53 int n;
54 char s[];
55 {
56 int i, c, j, len;
57
58 if ((c = n) < 0)
59 n = -n;
60
61 i = 0;
62 do {
63 s[i++] = n % 10 + '0';
64 } while ((n /= 10) > 0);
65
66 if (c < 0)
67 s[i++] = '-';
68
69 s[i] = '\0';
70
71 len = i--;
72
73 for (j = 0; i > j; j++, i--) {
74 c = s[i];
75 s[i] = s[j];
76 s[j] = c;
77 }
78
79 return len;
80 }
81
82 /*
83 * Like APPEND, and APPEND_CAP, APPEND_INT is an in-line function that
84 * stops us from calling sprintf over and over again.
85 */
86 #define APPEND_INT(ptr, i) \
87 ptr += itoa2(i, ptr);
88
89
90 #ifdef SERVER
91 #define ADDRLEN 10
92 #define MAXMACLEN 85
93 extern char *shiptypes[];
94 #define warning(x) fprintf(stderr,x)
95 #endif
96
97
98 char *getaddr(), *getaddr2();
99
100
101
102 /* This takes an MDISTR flagged message and makes it into a dist struct */
103 void
104 HandleGenDistr(message, from, to, dist)
105 char *message;
106 struct distress *dist;
107 unsigned char from, to;
108 {
109
110 char *mtext;
111 unsigned char i;
112
113 mtext = &message[ADDRLEN];
114 #ifndef SERVER
115 MZERO((char *) dist, sizeof(dist));
116 #else
117 bzero((char *) dist, sizeof(dist));
118 #endif
119
120 dist->sender = from;
121 dist->distype = mtext[0] & 0x1f;
122 dist->macroflag = ((mtext[0] & 0x20) > 0);
123 dist->fuelp = mtext[1] & 0x7f;
124 dist->dam = mtext[2] & 0x7f;
125 dist->shld = mtext[3] & 0x7f;
126 dist->etmp = mtext[4] & 0x7f;
127 dist->wtmp = mtext[5] & 0x7f;
128 dist->arms = mtext[6] & 0x1f;
129 dist->sts = mtext[7] & 0x7f;
130 dist->wtmpflag = ((dist->sts & PFWEP) != 0) ? 1 : 0;
131 dist->etempflag = ((dist->sts & PFENG) != 0) ? 1 : 0;
132 dist->cloakflag = ((dist->sts & PFCLOAK) != 0) ? 1 : 0;
133 dist->close_pl = mtext[8] & 0x7f;
134 dist->close_en = mtext[9] & 0x7f;
135 dist->tclose_pl = mtext[10] & 0x7f;
136 dist->tclose_en = mtext[11] & 0x7f;
137 dist->tclose_j = mtext[12] & 0x7f;
138 dist->close_j = mtext[13] & 0x7f;
139 dist->tclose_fr = mtext[14] & 0x7f;
140 dist->close_fr = mtext[15] & 0x7f;
141 i = 0;
142 while ((mtext[16 + i] & 0xc0) == 0xc0 && (i < 6)) {
143 dist->cclist[i] = mtext[16 + i] & 0x1f;
144 i++;
145 }
146 dist->cclist[i] = mtext[16 + i];
147 if (dist->cclist[i] == 0x80)
148 dist->pre_app = 1;
149 else
150 dist->pre_app = 0;
151 dist->preappend[0] = '\0';
152
153 if (mtext[16 + i + 1] != '\0') {
154 strncpy(dist->preappend, &mtext[16 + i + 1], MSG_LEN - 1);
155 dist->preappend[MSG_LEN - 1] = '\0';
156 }
157 }
158
159 /* this converts a dist struct to the appropriate text
160 (excludes F1->FED text bit).. sorry if this is not what we said
161 earlier jeff.. but I lost the paper towel I wrote it all down on */
162 void
163 Dist2Mesg(dist, buf)
164 struct distress *dist;
165 char *buf;
166 {
167 int len, i;
168
169 sprintf(buf, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
170 (dist->macroflag << 5) + (dist->distype),
171 dist->fuelp | 0x80,
172 dist->dam | 0x80,
173 dist->shld | 0x80,
174 dist->etmp | 0x80,
175 dist->wtmp | 0x80,
176 dist->arms | 0x80,
177 dist->sts | 0x80,
178 dist->close_pl | 0x80,
179 dist->close_en | 0x80,
180 dist->tclose_pl | 0x80,
181 dist->tclose_en | 0x80,
182 dist->tclose_j | 0x80,
183 dist->close_j | 0x80,
184 dist->tclose_fr | 0x80,
185 dist->close_fr | 0x80);
186
187 /* cclist better be terminated properly otherwise we hose here */
188 i = 0;
189 while (((dist->cclist[i] & 0xc0) == 0xc0)) {
190 buf[16 + i] = dist->cclist[i];
191 i++;
192 }
193 /* get the pre/append cclist terminator in there */
194 buf[16 + i] = dist->cclist[i];
195 buf[16 + i + 1] = '\0';
196
197 len = 16 + i + 1;
198 if (dist->preappend[0] != '\0') {
199 strncat(buf, dist->preappend, MSG_LEN - len); /* false sense of
200 security? */
201 buf[MSG_LEN - 1] = '\0';
202 }
203 }
204
205 /* small permutation on the newmacro code... this takes a pointer to
206 ** a distress structure and a pointer to a macro syntax string,
207 ** and converts it into a line of text.
208 ** 9/1/93 - jn
209 */
210 int
211 makedistress(dist, cry, pm)
212 struct distress *dist; /* the info */
213 char *cry; /* the call for help! (output) - should be
214 array */
215 char *pm; /* macro to parse, used for distress and
216 macro */
217 {
218 char buf1[10 * MAXMACLEN];
219 char *pbuf1;
220 char buf2[10 * MAXMACLEN];
221 char buf3[10 * MAXMACLEN];
222 char tmp[10 * MAXMACLEN];
223 int index = 0;
224 int index2 = 0;
225 int index3 = 0;
226 int cap = 0;
227 struct player *sender;
228 struct player *j;
229 struct planet *l;
230 char *strcap();
231 #ifndef SERVER
232 extern int ping_tloss_sc; /* total % loss 0--100, server to client */
233 extern int ping_tloss_cs; /* total % loss 0--100, client to server */
234 extern int ping_av; /* average rt */
235 extern int ping_sd; /* standard deviation */
236 #endif
237 char c;
238
239
240 sender = &players[dist->sender];
241
242 if (!(*pm)) {
243 cry[0] = '\0';
244 return (0);
245 }
246 buf1[0] = '\0';
247 pbuf1 = buf1;
248
249 /* first step is to substitute variables */
250 while (*pm) {
251 if (*pm == '%') {
252 pm++;
253
254 if (!pm)
255 continue;
256
257 switch (c = *(pm++)) {
258 case ' ':
259 APPEND(pbuf1, " \0");
260 break;
261 case 'O': /* push a 3 character team name into buf */
262 cap = 1;
263 case 'o': /* push a 3 character team name into buf */
264 APPEND_CAP(pbuf1, cap, teaminfo[sender->p_teami].shortname);
265 cap = 0;
266 break;
267 case 'a': /* push army number into buf */
268 APPEND_INT(pbuf1, dist->arms);
269 break;
270 case 'd': /* push damage into buf */
271 APPEND_INT(pbuf1, dist->dam);
272 break;
273 case 's': /* push shields into buf */
274 APPEND_INT(pbuf1, dist->shld);
275 break;
276 case 'f': /* push fuel into buf */
277 APPEND_INT(pbuf1, dist->fuelp);
278 break;
279 case 'w': /* push wtemp into buf */
280 APPEND_INT(pbuf1, dist->wtmp);
281 break;
282 case 'e': /* push etemp into buf */
283 APPEND_INT(pbuf1, dist->etmp);
284 break;
285
286 case 'P': /* push player id into buf */
287 case 'G': /* push friendly player id into buf */
288 case 'H': /* push enemy target player id into buf */
289
290 case 'p': /* push player id into buf */
291 case 'g': /* push friendly player id into buf */
292 case 'h': /* push enemy target player id into buf */
293
294 switch (c) {
295 case 'p':
296 j = &players[dist->tclose_j];
297 break;
298 case 'g':
299 j = &players[dist->tclose_fr];
300 break;
301 case 'h':
302 j = &players[dist->tclose_en];
303 break;
304 case 'P':
305 j = &players[dist->close_j];
306 break;
307 case 'G':
308 j = &players[dist->close_fr];
309 break;
310 default:
311 j = &players[dist->close_en];
312 break;
313 }
314 tmp[0] = j->p_mapchars[1];
315 tmp[1] = '\0';
316 APPEND(pbuf1, tmp);
317 break;
318
319 case 'n': /* push planet armies into buf */
320 l = &planets[dist->tclose_pl];
321 APPEND_INT(pbuf1,
322 ((l->pl_info & idx_to_mask(sender->p_teami))
323 ? l->pl_armies : -1));
324 break;
325 case 'B':
326 cap = 1;
327 case 'b': /* push planet into buf */
328 l = &planets[dist->close_pl];
329 tmp[0] = l->pl_name[0] - 'A' + 'a';
330 tmp[1] = l->pl_name[1];
331 tmp[2] = l->pl_name[2];
332 tmp[3] = '\0';
333 APPEND_CAP(pbuf1, cap, tmp);
334 cap = 0;
335 break;
336 case 'L':
337 cap = 1;
338 case 'l': /* push planet into buf */
339 l = &planets[dist->tclose_pl];
340 tmp[0] = l->pl_name[0] - 'A' + 'a';
341 tmp[1] = l->pl_name[1];
342 tmp[2] = l->pl_name[2];
343 tmp[3] = '\0';
344 APPEND_CAP(pbuf1, cap, tmp);
345 cap = 0;
346 break;
347 case 'Z': /* push a 3 character team name into buf */
348 cap = 1;
349 case 'z': /* push a 3 character team name into buf */
350 l = &planets[dist->tclose_pl];
351 APPEND_CAP(pbuf1, cap,
352 teaminfo[mask_to_idx(l->pl_owner)].shortname);
353 cap = 0;
354 break;
355 case 't': /* push a team character into buf */
356 l = &planets[dist->tclose_pl];
357 tmp[0] = teaminfo[mask_to_idx(l->pl_owner)].letter;
358 tmp[1] = '\0';
359 APPEND(pbuf1, tmp);
360 break;
361 case 'T': /* push my team into buf */
362 tmp[0] = teaminfo[sender->p_teami].letter;
363 tmp[1] = '\0';
364 APPEND(pbuf1, tmp);
365 break;
366 case 'c': /* push my id char into buf */
367 tmp[0] = sender->p_mapchars[1];
368 tmp[1] = '\0';
369 APPEND(pbuf1, tmp);
370 break;
371 case 'W': /* push WTEMP flag into buf */
372 if (dist->wtmpflag)
373 tmp[0] = '1';
374 else
375 tmp[0] = '0';
376 tmp[1] = '\0';
377 APPEND(pbuf1, tmp);
378 break;
379 case 'E': /* push ETEMP flag into buf */
380 if (dist->etempflag)
381 tmp[0] = '1';
382 else
383 tmp[0] = '0';
384 tmp[1] = '\0';
385 APPEND(pbuf1, tmp);
386 break;
387 case 'K':
388 cap = 1;
389 case 'k':
390 if (cap)
391 j = &players[dist->tclose_en];
392 else
393 j = sender;
394
395 if (j->p_ship->s_type == STARBASE)
396 sprintf(tmp, "%5.2f", j->p_stats.st_sbkills / 100.0);
397 else
398 sprintf(tmp, "%5.2f", (j->p_stats.st_kills + j->p_stats.st_tkills) / 100.0);
399 APPEND(pbuf1, tmp);
400 break;
401
402 case 'U': /* push player name into buf */
403 cap = 1;
404 case 'u': /* push player name into buf */
405 j = &players[dist->tclose_en];
406 APPEND_CAP(pbuf1, cap, j->p_name);
407 cap = 0;
408 break;
409 case 'I': /* my player name into buf */
410 cap = 1;
411 case 'i': /* my player name into buf */
412 APPEND_CAP(pbuf1, cap, sender->p_name);
413 cap = 0;
414 break;
415 case 'S': /* push ship type into buf */
416 #ifndef SERVER
417 *pbuf1++ = sender->p_ship->s_desig[0];
418 *pbuf1++ = sender->p_ship->s_desig[1];
419 #else
420 APPEND(pbuf1, shiptypes[sender->p_ship->s_type]);
421 #endif
422 break;
423
424 #ifdef SERVER
425 case 'v': /* push average ping round trip time into buf */
426 case 'V': /* push ping stdev into buf */
427 case 'y': /* push packet loss into buf */
428 APPEND(pbuf1, "0\0");
429 case 'M': /* push capitalized lastMessage into buf */
430 case 'm': /* push lastMessage into buf */
431 break;
432 #else
433 case 'M': /* push capitalized lastMessage into buf */
434 cap = 1;
435 case 'm': /* push lastMessage into buf */
436 APPEND_CAP(pbuf1, cap, lastMessage);
437 cap = 0;
438 break;
439
440 case 'v': /* push average ping round trip time into buf */
441 APPEND_INT(pbuf1, ping_av);
442 break;
443
444 case 'V': /* push ping stdev into buf */
445 APPEND_INT(pbuf1, ping_sd);
446 break;
447
448 case 'y': /* push packet loss into buf */
449 /* this is the weighting formula used be socket.c ntserv */
450 APPEND_INT(pbuf1, (2 * ping_tloss_sc + ping_tloss_cs) / 3);
451 break;
452 #endif
453
454 case '*': /* push %} into buf */
455 APPEND(pbuf1, "%*\0");
456 break;
457 case '}': /* push %} into buf */
458 APPEND(pbuf1, "%}\0");
459 break;
460 case '{': /* push %{ into buf */
461 APPEND(pbuf1, "%{\0");
462 break;
463 case '!': /* push %! into buf */
464 APPEND(pbuf1, "%!\0");
465 break;
466 case '?': /* push %? into buf */
467 APPEND(pbuf1, "%?\0");
468 break;
469 case '%': /* push %% into buf */
470 APPEND(pbuf1, "%%\0");
471 break;
472 default:
473 /* try to continue
474 ** bad macro character is skipped entirely,
475 ** the message will be parsed without whatever %. has occurred. - jn
476 */
477 warning("Bad Macro character in distress!");
478 fprintf(stderr, "Unrecognizable special character in distress pass 1: %c\n", *(pm - 1));
479 break;
480 }
481 } else {
482 tmp[0] = *pm;
483 tmp[1] = '\0';
484 APPEND(pbuf1, tmp);
485 pm++;
486 }
487
488 }
489
490 *pbuf1 = '\0';
491
492 /* second step is to evaluate tests, buf1->buf2 */
493 testmacro(buf1, buf2, &index, &index2);
494 buf2[index2] = '\0';
495
496 if (index2 <= 0) {
497 cry[0] = '\0';
498 return (0);
499 }
500 index2 = 0;
501
502 /* third step is to include conditional text, buf2->buf3 */
503 condmacro(buf2, buf3, &index2, &index3, 1);
504
505 if (index3 <= 0) {
506 cry[0] = '\0';
507 return (0);
508 }
509 buf3[index3] = '\0';
510
511 cry[0] = '\0';
512 strncat(cry, buf3, MSG_LEN);
513
514 return (index3);
515 }
516
517 int
518 testmacro(bufa, bufb, inda, indb)
519 char *bufa;
520 char *bufb;
521 int *inda;
522 int *indb;
523 {
524 int state = 0;
525
526 if (*indb >= 10 * MAXMACLEN)
527 return 0;
528 /* maybe we should do something more "safe" here (and at other returns)? */
529
530
531 while (bufa[*inda] && (*indb < 10 * MAXMACLEN)) {
532 if (state) {
533 switch (bufa[(*inda)++]) {
534 case '*': /* push %* into buf */
535 if (*indb < 10 * MAXMACLEN - 2) {
536 bufb[*indb] = '%';
537 (*indb)++;
538 bufb[*indb] = '*';
539 (*indb)++;
540 } else
541 return (0); /* we are full, so we are done */
542 state = 0;
543 continue;
544 break;
545
546 case '%': /* push %% into buf */
547 if (*indb < 10 * MAXMACLEN - 2) {
548 bufb[*indb] = '%';
549 (*indb)++;
550 bufb[*indb] = '%';
551 (*indb)++;
552 } else
553 return (0); /* we are full, so we are done */
554 state = 0;
555 continue;
556 break;
557
558 case '{': /* push %{ into buf */
559 if (*indb < 10 * MAXMACLEN - 2) {
560 bufb[*indb] = '%';
561 (*indb)++;
562 bufb[*indb] = '{';
563 (*indb)++;
564 } else
565 return (0); /* we are full, so we are done */
566 state = 0;
567 continue;
568 break;
569
570 case '}': /* push %} into buf */
571 if (*indb < 10 * MAXMACLEN - 2) {
572 bufb[*indb] = '%';
573 (*indb)++;
574 bufb[*indb] = '}';
575 (*indb)++;
576 } else
577 return (0); /* we are full, so we are done */
578 state = 0;
579 continue;
580 break;
581
582 case '!': /* push %! into buf */
583 if (*indb < 10 * MAXMACLEN - 2) {
584 bufb[*indb] = '%';
585 (*indb)++;
586 bufb[*indb] = '!';
587 (*indb)++;
588 } else
589 return (0); /* we are full, so we are done */
590 state = 0;
591 continue;
592 break;
593
594 case '?': /* the dreaded conditional, evaluate it */
595 bufb[*indb] = '0' + solvetest(bufa, inda);
596 (*indb)++;
597 state = 0;
598 continue;
599 break;
600
601 default:
602 warning("Bad character in Macro!");
603 printf("Unrecognizable special character in macro pass2: %c Trying to continue.\n",
604 bufa[(*inda) - 1]);
605 state = 0;
606 continue;
607 break;
608 }
609 }
610 if (bufa[*inda] == '%') {
611 state++;
612 (*inda)++;
613 continue;
614 }
615 state = 0;
616
617
618 if (*indb < 10 * MAXMACLEN) {
619 bufb[*indb] = bufa[*inda];
620 (*inda)++;
621 (*indb)++;
622 } else
623 return (0);
624 }
625
626 return (0);
627 }
628
629 int
630 solvetest(bufa, inda)
631 char *bufa;
632 int *inda;
633 {
634 int state = 0;
635 char bufh[10 * MAXMACLEN];
636 char bufc[10 * MAXMACLEN];
637 int indh = 0, indc = 0, i;
638 char operation;
639
640
641 while (bufa[*inda] &&
642 bufa[*inda] != '<' &&
643 bufa[*inda] != '>' &&
644 bufa[*inda] != '=') {
645
646 bufh[indh++] = bufa[(*inda)++];
647 }
648 bufh[indh] = '\0';
649
650 operation = bufa[(*inda)++];
651
652 while (bufa[*inda] &&
653 !(state &&
654 ((bufa[*inda] == '?') ||
655 (bufa[*inda] == '{')))) {
656
657 if (state && (bufa[*inda] == '%' ||
658 bufa[*inda] == '!' ||
659 bufa[*inda] == '}')) {
660 bufc[indc++] = '%';
661 } else if (bufa[*inda] == '%') {
662 state = 1;
663 (*inda)++;
664 continue;
665 }
666 state = 0;
667 bufc[indc++] = bufa[(*inda)++];
668 }
669 bufc[indc] = '\0';
670
671 if (bufa[*inda])
672 (*inda)--;
673
674 if (!operation) /* incomplete is truth, just ask Godel */
675 return (1);
676
677 switch (operation) {
678 case '=': /* character by character equality */
679 if (indc != indh)
680 return (0);
681 for (i = 0; i < indc; i++) {
682 if (bufc[i] != bufh[i])
683 return (0);
684 }
685 return (1);
686 break;
687
688 case '<':
689 if (atoi(bufh) < atoi(bufc))
690 return (1);
691 else
692 return (0);
693 break;
694
695 case '>':
696 if (atoi(bufh) > atoi(bufc))
697 return (1);
698 else
699 return (0);
700 break;
701
702 default:
703 warning("Bad operation in Macro!");
704 printf("Unrecognizable operation in macro pass3: %c Trying to continue.\n",
705 operation);
706 return (1); /* don't know what happened, pretend we do */
707 break;
708 }
709 }
710
711 int
712 condmacro(bufa, bufb, inda, indb, flag)
713 char *bufa;
714 char *bufb;
715 int *inda;
716 int *indb;
717 int flag;
718 {
719 int newflag, include;
720 int state = 0;
721
722
723 if (*indb >= MAXMACLEN)
724 return 0;
725
726 include = flag;
727
728 while (bufa[*inda] && (*indb < MAXMACLEN)) {
729 if (state) {
730 switch (bufa[(*inda)++]) {
731 case '}': /* done with this conditional, return */
732 return (0);
733 break;
734
735 case '{': /* handle new conditional */
736 if (*indb > 0) {
737 (*indb)--;
738 if (bufb[*indb] == '0')
739 newflag = 0;
740 else
741 newflag = 1;
742 } else /* moron starting with cond, assume true */
743 newflag = 1;
744
745 if (include)
746 condmacro(bufa, bufb, inda, indb, newflag);
747 else {
748 (*indb)++;
749 *inda = skipmacro(bufa, *inda);
750 }
751
752 state = 0;
753 continue;
754 break;
755
756 case '!': /* handle not indicator */
757 if (flag)
758 include = 0;
759 else
760 include = 1;
761
762 state = 0;
763 continue;
764 break;
765
766 case '%': /* push % into buf */
767 if (include) {
768 if (*indb < MAXMACLEN) {
769 bufb[*indb] = '%';
770 (*indb)++;
771 } else
772 return (0);
773 }
774 state = 0;
775 continue;
776
777 default:
778 warning("Bad character in Macro!");
779 printf("Unrecognizable special character in macro pass4: %c Trying to continue.\n",
780 bufa[(*inda) - 1]);
781 }
782 }
783 if (bufa[*inda] == '%') {
784 state++;
785 (*inda)++;
786 continue;
787 }
788 state = 0;
789
790
791 if (include) {
792 if (*indb < MAXMACLEN) {
793 bufb[*indb] = bufa[*inda];
794 (*inda)++;
795 (*indb)++;
796 } else
797 return (0);
798 } else
799 (*inda)++;
800 }
801 return (0);
802 }
803
804 int
805 skipmacro(buf, index)
806 char buf[];
807 int index;
808 {
809 int state = 0;
810 int end = 0;
811
812 if (index == 0)
813 index++;
814
815 while (buf[index] && !end) {
816 if (state) {
817 switch (buf[index++]) {
818 case '{':
819 index = skipmacro(buf, index);
820 continue;
821 break;
822 case '}':
823 end = 1;
824 continue;
825 break;
826 case '!':
827 case '%':
828 state = 0;
829 continue;
830 break;
831 default:
832 warning("Bad character in Macro!");
833 printf("Unrecognizable special character in macro pass5: %c Trying to continue.\n",
834 buf[index - 1]);
835 }
836 }
837 if (buf[index] == '%') {
838 state++;
839 index++;
840 continue;
841 }
842 state = 0;
843 index++;
844 }
845
846 return (index);
847 }
848
849
850 /* return a pointer to a capitalized copy of string s */
851 char *
852 strcap(s)
853 char *s;
854 {
855 static char buf[256]; /* returns static */
856 register char *t = buf;
857
858 while (*s) {
859 if (islower(*s))
860 *t++ = toupper(*s++);
861 else
862 *t++ = *s++;
863 }
864 *t = 0;
865 if (buf[255]) {
866 fprintf(stderr, "ERROR: String constant overwritten\n");
867 return NULL;
868 }
869 return buf;
870 }