Mercurial > ~darius > hgwebdir.cgi > paradise_client
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 } |