blob: 54f6701f856d5402357ef1f942b191c6087c4eee [file] [log] [blame]
PulkoMandy17fc7592022-07-28 18:27:54 +02001/* TODO:
2
3 ---- HIGHEST PRIORITY ----
4
5 * #ifndef
6
7 * #if/#elif - Bearbeitung
8
9 * leere argument-/tokenlists erlauben
10
11 * Anzahl der Argumente checken (auch zuviele ergeben einen Error)
12
13 * bei REDEFINING und allowredefinition=0 tokenlist genau ueberpruefen
14
15 * Aufteilen in mehrere Sourcen main.c pplists.c etc.
16 * Einige Variablen umbenennen (x,y,i,j,l,n etc =8)
17
18 -----------------------------------------------------------------
19
20 * Verbesserungen:
21 * - Nach malloc()/vor free() ueberpruefen ob NULL-Pointer
22 * - Statt per dlen per Ptr2EOL abfragen..
23
24 * Fragen an Volker:
25 * - _ alleine ein Identifier ? Ja
26
27 ---- LOWEST PRIORITY ----
28
29 * - Token loeschen, wenn nur noch TokenList benutzt wird.
30
31 * - ParseIdent.. optimieren
32
33 * - Rest optimieren =8)
34
35 * - PreParsing umschreiben.. __LINE__ muss mit der echten
36 * Zeilennummer uebereinstimmen (die LFs drinlassen)
37 */
38
39/*
40 * PreProcessor
41 * $VER: VBPP V0.00 (19 Sep 1995)
42 * (w) 1995 by Thorsten Schaaps
43 */
44
45#include <time.h>
46
47#include "vbc.h"
48#include "vbpp.h"
49
50/*vb: */
51static char FILE_[]=__FILE__;
52
53/*vb: */
54char pp_version[] = "vbpp V0.00 (w) 1995 by Thorsten Schaaps";
55
56 /* #define MAXIFNESTING 1024 *//*vb: ifnesting==incnesting */
57
58FILE *in[MAXINCNESTING]; /* Sourcefiles */
59int zn[MAXINCNESTING]; /* Zeilennummern */
60char *filenames[MAXINCNESTING]; /* Filenamen */
61int incnesting; /* aktuelle Verschachtelungstiefe */
62unsigned long linenr; /* Zeilennummer */
63
64char *incpath[MAXINCPATHS] =
65{"vinclude:"}; /* Includepfade */
66
67int incpathc = 1; /* Anzahl der Includepfade */
68
69char ppstring[MAXPPINPUT];
70
71int cmtnesting = 0; /* aktuelle Kommentar-Versch.-Tiefe */
72
73 /*int ifnesting; *//*vb: *//* aktuelle IF-Tiefe */
74/*vb: ifnesting==incnesting */
75short ifstatus[MAXINCNESTING]; /* Array fuer Status-Verschachtelung */
76int if_cnt; /* Zaehler fuer #if's waehrend do_output=0 */
77int abs_if_cnt; /* zaehlt auch waehrend do_output */
78
79int do_output = 1; /* Flag zur Erzeugung eines Outputs */
80
81struct strnode *strlist;
82
83struct mnode *mlist;
84
85int did_expand;
86
87/* Temporaere Debugging-Routinen */
88void PrintSN(struct strnode *tl)
89{
90 switch (tl->type) {
91 case NORMAL:
92 printf(" Normal........:");
93 break;
94 case PP_IDENT:
95 printf(" Identifier....:");
96 break;
97 case ARGUMENT:
98 printf(" Argument Nr.%2d:", tl->number);
99 break;
100 case NUMBER:
101 printf(" Number........:");
102 break;
103 case PP_STR:
104 printf(" String........:");
105 break;
106 case SPACE:
107 printf(" Space.........:");
108 break;
109 case SPECIAL:
110 printf(" Special..Nr.%2d:", tl->flags);
111 break;
112 default:
113 printf(" unknown..Nr.%2d:", tl->type);
114 break;
115 }
116 printf(" %s\n", tl->str);
117}
118void PrintTL(struct strnode *tl)
119{
120
121#ifdef bla
122
123 if (tl) {
124 printf("TokenList:\n");
125 while (tl) {
126 PrintSN(tl);
127 tl = tl->next;
128 }
129 }
130#endif
131
132}
133
134
135/* ******* Listen-Funktionen ******* */
136
137/* AddMakroNode - Fuegt eine Node an den Anfang einer Liste ein */
138void AddMakroNode(struct mnode **list, struct mnode *node)
139{
140
141 if (DEBUG & 32)
142 puts("AddMakroNode");
143
144 if (node) {
145 node->prev = NULL;
146 node->next = *list;
147 *list = node;
148 if (node->next)
149 node->next->prev = node;
150 }
151}
152
153
154/* AddStrNode - Fuegt eine Node in die Liste ein */
155void AddStrNode(struct strnode **list, struct strnode *node, char *str)
156{
157
158 if (DEBUG & 32)
159 puts("AddStrNode");
160
161
162 if (node || str) {
163 if (!node)
164 node = (struct strnode *) malloc(sizeof(struct strnode));
165 /* HIER: Rueckgabewert wegen Fehler ! */
166 if (!node) {
167 error(196);
168 } else {
169 node->prev = NULL;
170 node->next = *list;
171 if (str)
172 node->str = str;
173 *list = node;
174 if (node->next)
175 node->next->prev = node;
176 }
177 }
178}
179
180
181/* AddStrNodeBehind - Fuegt eine Node ans Ende der Liste ein */
182void AddStrNodeBehind(struct strnode **list, struct strnode *node, char *str)
183{
184 struct strnode *listnode;
185
186 if (DEBUG & 32)
187 puts("AddStrNodeBehind");
188
189
190 if (node || str) {
191 if (!node)
192 node = (struct strnode *) malloc(sizeof(struct strnode));
193 if (!node) {
194 error(196);
195 } else {
196 if (!*list) {
197 node->prev = NULL;
198 node->next = NULL;
199 *list = node;
200 } else {
201 listnode = *list;
202 while (listnode->next) {
203 listnode = listnode->next;
204 }
205 node->prev = listnode;
206 node->next = NULL;
207 listnode->next = node;
208 }
209 if (str)
210 node->str = str;
211 }
212 }
213}
214
215
216/* RemMakroNode - Entfernt eine Node aus der Liste ohne sie zu loeschen */
217void RemMakroNode(struct mnode **list, struct mnode *node)
218{
219
220 if (DEBUG & 32)
221 puts("RemMakroNode");
222
223
224 if (node->prev) {
225 if (node->next)
226 node->next->prev = node->prev;
227 node->prev->next = node->next;
228 } else {
229 if (node->next)
230 node->next->prev = NULL;
231 *list = node->next;
232 }
233 node->next = node->prev = NULL;
234}
235
236/* InsertMakroNode - Setzt eine Node hinter einer anderen ein */
237void InsertMakroNode(struct mnode **list, struct mnode *node, struct mnode *behind)
238{
239
240 if (DEBUG & 32)
241 puts("InsertMakroNode");
242
243
244 if (behind) {
245 node->prev = behind;
246 node->next = behind->next;
247 behind->next = node;
248 if (node->next)
249 node->next->prev = node;
250 } else
251 AddMakroNode(list, node);
252}
253
254/* RemStrNode - Entfernt eine Node aus der Liste ohne sie zu loeschen */
255void RemStrNode(struct strnode **list, struct strnode *node)
256{
257
258 if (DEBUG & 32)
259 puts("RemStrNode");
260
261
262 if (node->prev) {
263 if (node->next)
264 node->next->prev = node->prev;
265 node->prev->next = node->next;
266 } else {
267 if (node->next)
268 node->next->prev = NULL;
269 *list = node->next;
270 }
271 node->next = node->prev = NULL;
272}
273
274
275/* FindMakroNode - sucht den passenden Eintrag in der Liste
276 * len=0 - der gesamte String muss uebereinstimmen
277 * len>0 - die ersten len Zeichen muessen stimmen
278 */
279struct mnode *FindMakroNode(struct mnode *list, char *str, int len)
280{
281
282 if (DEBUG & 32)
283 puts("FindMakroNode");
284
285 while (list) {
286 if (len) {
287 if ((strlen(list->name) == len) && (!strncmp(list->name, str, len)))
288 return (list);
289 } else {
290 if (!strcmp(list->name, str))
291 return (list);
292 }
293 list = list->next;
294 }
295 return (0);
296}
297
298
299/* DelMakroNode - gibt den gesamten Speicher einer Node frei, ist list#NULL
300 * wird die Node vorher aus der Liste entfernt
301 */
302void DelMakroNode(struct mnode **list, struct mnode *node)
303{
304
305 if (DEBUG & 32)
306 puts("DelMakroNode");
307
308
309 if (node) {
310 if (list && *list)
311 RemMakroNode(list, node);
312 if (node->name)
313 free(node->name);
314 if (node->args)
315 free(node->args);
316 if (node->token)
317 free(node->token);
318 if (node->tokenlist)
319 DelStrList(&node->tokenlist);
320 free(node);
321 }
322}
323
324
325/* DelStrNode - gibt den gesamten Speicher einer Node frei, ist list#NULL
326 * wird die Node vorher aus der Liste entfernt
327 */
328void DelStrNode(struct strnode **list, struct strnode *node)
329{
330
331 if (DEBUG & 32)
332 puts("DelStrNode");
333
334
335 if (node) {
336 if (list && *list)
337 RemStrNode(list, node);
338 if (node->str)
339 free(node->str);
340 free(node);
341 }
342}
343
344void MergeStrNodes(struct strnode *prev, struct strnode *next)
345{
346 /* next will now be deleted and prev->str will be */
347 /* the joined strings from prev&next */
348 char *newstr;
349/*vb: */
350 char c, *s, *d;
351
352 if (DEBUG & 32)
353 puts("MergeStrNodes");
354
355
356 newstr = (char *) malloc(prev->len + next->len + 1);
357/*vb: string-Routinen ersetzt (hoffentlich schneller)
358 strcpy(newstr,prev->str);
359 strcat(newstr,next->str);
360 */
361 d = newstr;
362 s = prev->str;
363 do {
364 c = *s++;
365 *d++ = c;
366 } while (c);
367 d--;
368 s = next->str;
369 do {
370 c = *s++;
371 *d++ = c;
372 } while (c);
373
374 if (prev->str)
375 free(prev->str); /*vb: wenn prev->str==0 knallts doch schon oben? */
376 prev->str = newstr;
377 prev->len += next->len;
378 DelStrNode(NULL, next);
379}
380
381/* DelMakroList - loescht eine gesamte Liste */
382void DelMakroList(struct mnode **list)
383{
384
385 if (DEBUG & 32)
386 puts("DelMakroList");
387
388
389 while (*list)
390 DelMakroNode(list, *list);
391 /* *list=NULL; *//*vb: *list==0 */
392}
393
394
395/* DelStrList - loescht eine gesamte Liste samt der Nodes/Strings */
396void DelStrList(struct strnode **list)
397{
398
399 if (DEBUG & 32)
400 puts("DelStrList");
401
402
403 while (*list)
404 DelStrNode(list, *list);
405 /* *list=NULL; *//*vb: *list==0 */
406}
407
408/* AllocSpace - erzeugt eine StrNode vom Typ Space */
409struct strnode *AllocSpace()
410{
411 struct strnode *newnode;
412 char *newstr;
413
414
415 if (DEBUG & 32)
416 puts("AllocSpace");
417
418
419 newstr = (char *) malloc(2);
420 if (newstr) {
421 newstr[0] = ' ';
422 newstr[1] = 0;
423 newnode = (struct strnode *) malloc(sizeof(struct strnode));
424 if (newnode) {
425 newnode->str = newstr;
426 newnode->type = SPACE;
427 newnode->len = 1;
428 newnode->next = newnode->prev = NULL;
429 newnode->flags = newnode->number = 0;
430 return (newnode);
431 }
432 }
433 return (NULL);
434}
435
436
437/* CloneStrList - erstellt eine exakte Kopie der Liste oder eines Ausschnittes */
438/* wenn listend#NULL */
439struct strnode *CloneStrList(struct strnode *list, struct strnode *listend)
440{
441 struct strnode *prevnode = NULL, *newnode, *newlist = NULL;
442 char *newstr;
443
444 if (DEBUG & 32)
445 puts("CloneStrList");
446
447
448 while (list) {
449 newnode = (struct strnode *) malloc(sizeof(struct strnode));
450 if (!newnode) {
451 DelStrList(&newlist);
452 return (NULL);
453 }
454 newstr = (char *) malloc(list->len + 1);
455 if (!newstr) {
456 free(newnode);
457 DelStrList(&newlist);
458 return (NULL);
459 }
460 strcpy(newstr, list->str);
461 newnode->str = newstr;
462 newnode->len = list->len;
463 newnode->flags = list->flags;
464 newnode->type = list->type;
465 newnode->number = list->number;
466 newnode->next = NULL;
467 newnode->prev = prevnode;
468
469 if (prevnode)
470 prevnode->next = newnode;
471 else
472 newlist = newnode;
473 prevnode = newnode;
474
475 if (listend && list == listend)
476 list = NULL;
477 else
478 list = list->next;
479 }
480 return (newlist);
481}
482
483
484/* DoMakroFunction - erstellt eine StrList entsprechend des Function-Makros */
485struct strnode *DoMakroFunction(struct mnode *makro)
486{
487 struct strnode *result = NULL;
488 char *newstr = NULL, *timestr = NULL;
489 int len, type;
490 time_t timevalue;
491
492 if (DEBUG & 32)
493 puts("DoMakroFunction");
494
495
496 if (makro->flags & FUNCTION) {
497 switch (makro->funcnum) {
498 case FUNCLINE:
499 newstr = (char *) malloc(11);
500 if (!newstr)
501 return (NULL);
502 sprintf(newstr, "%lu", linenr);
503 len = strlen(newstr);
504 type = NUMBER;
505 break;
506 case FUNCFILE:
507 len = strlen(filenames[incnesting]);
508 newstr = (char *) malloc(len + 1 + 2);
509 if (!newstr)
510 return (NULL);
511 *newstr = '\"';
512 strcpy((newstr + 1), filenames[incnesting]);
513 strcat(newstr, "\"");
514 type = PP_STR;
515 break;
516 case FUNCDATE:
517 type = PP_STR;
518 newstr = (char *) malloc(14);
519 if (!newstr)
520 return (NULL);
521 timevalue = time(0);
522 timestr = ctime(&timevalue);
523 newstr[0] = '\"';
524 strncpy(newstr + 1, timestr + 4, 7); /* copy 'Mmm dd ' */
525 strcpy(newstr + 8, timestr + 20); /* copy 'yyyy' */
526 newstr[12] = '\"';
527 newstr[13] = 0;
528 len = 13;
529 break;
530 case FUNCTIME:
531 type = PP_STR;
532 newstr = (char *) malloc(11);
533 if (!newstr)
534 return (NULL);
535 timevalue = time(0);
536 timestr = ctime(&timevalue);
537 newstr[0] = '\"';
538 strncpy(newstr + 1, timestr + 11, 8); /* copy 'hh:mm:ss' */
539 newstr[9] = '\"';
540 newstr[10] = 0;
541 len = 10;
542 break;
543 default:
544 return (NULL);
545 break;
546 }
547 result = (struct strnode *) malloc(sizeof(struct strnode));
548 if (!result) {
549 if (newstr)
550 free(newstr);
551 return (NULL);
552 }
553 result->prev = result->next = NULL;
554 result->str = newstr;
555 result->len = len;
556 result->number = result->flags = 0;
557 result->type = type;
558 }
559 return (result);
560}
561
562
563/* ******* String-Funktionen ****** */
564
565/* Str2List - parsed einen String in eine StrList */
566struct strnode *Str2List(char *str)
567{
568 struct strnode *newlist = NULL, *newnode = NULL;
569 char *temp, *string;
570 int length, type, flags;
571
572 if (DEBUG & 32)
573 puts("Str2List");
574
575 while (*str) {
576 flags = 0;
577/*vb: casts eingefuegt */
578 if (isspace((unsigned char) *str)) { /* Spaces parsen */
579 temp = str + 1;
580 length = 1;
581 while (*temp && isspace((unsigned char) *temp)) {
582 temp++;
583 length++;
584 }
585 type = SPACE;
586 } else if (*str == '\"') { /* String parsen */
587 temp = str + 1;
588 length = 2;
589 while (*temp && *temp != '\"')
590 if (*temp == '\\') {
591 temp += 2;
592 length += 2;
593 } else {
594 temp++;
595 length++;
596 }
597 type = PP_STR;
598 } else if (*str == '\'') { /* String parsen */
599 temp = str + 1;
600 length = 2;
601 while (*temp && *temp != '\'')
602 if (*temp == '\\') {
603 temp += 2;
604 length += 2;
605 } else {
606 temp++;
607 length++;
608 }
609 type = PP_STR;
610 } else if (isdigit((unsigned char) *str) || (*str == '.' && isdigit((unsigned char) *(str + 1)))) {
611 /* Zahlen parsen */
612 temp = str;
613 length = 0;
614 while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) {
615 temp++;
616 length++;
617 }
618 if (*temp == '.') {
619 temp++;
620 length++;
621 if (isdigit((unsigned char) *temp) || *temp == 'e' || *temp == 'E')
622 while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) {
623 temp++;
624 length++;
625 }
626 }
627 if (*(temp - 1) == 'e' || *(temp - 1) == 'E')
628 if (isdigit((unsigned char) *temp) || *temp == '+' || *temp == '-') {
629 temp++;
630 length++;
631 while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) {
632 temp++;
633 length++;
634 }
635 }
636 type = NUMBER;
637 } else if (isalpha((unsigned char) *str) || *str == '_') { /* moegl. Identifier parsen */
638 temp = str + 1;
639 length = 1;
640 while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) {
641 temp++;
642 length++;
643 }
644 type = PP_IDENT;
645 } else if (*str) { /* alles andere als einzelne Zeichen */
646 length = 1;
647 type = NORMAL;
648 }
649 string = (char *) malloc(length + 1);
650 if (!string) {
651 error(196);
652 DelStrList(&newlist);
653 return (NULL);
654 }
655 strncpy(string, str, length);
656 string[length] = 0;
657 str += length;
658
659 newnode = (struct strnode *) malloc(sizeof(struct strnode));
660 if (!newnode) {
661 error(196);
662 if (string)
663 free(string);
664 return (NULL);
665 }
666 newnode->str = string;
667 newnode->len = length;
668 newnode->flags = flags;
669 newnode->type = type;
670
671 AddStrNodeBehind(&newlist, newnode, NULL);
672 }
673 return (newlist);
674}
675
676/* List2Str - schreibt eine Liste als String zurueck */
677int List2Str(struct strnode *list, char *str, int maxchars)
678{
679 int len = 0;
680 char c, *p;
681
682 if (DEBUG & 32)
683 puts("List2Str");
684
685
686 *str = 0;
687 if (list) {
688 while (list) {
689 if ((len + (list->len)) > (maxchars - 1)) {
690 error(177);
691 return (0);
692 } else {
693 /*vb: */
694 p = list->str;
695 do {
696 c = *p++;
697 *str++ = c;
698 } while (c);
699 str--;
700/* strcat(str,list->str); */
701 len += list->len;
702 }
703 list = list->next;
704 }
705 return (len + 1);
706 } else {
707 *str = 0;
708 return (1);
709 }
710}
711
712/* ListLen - ermittelt die Laenge einer Str-Liste (in Zeichen) */
713int ListLen(struct strnode *list)
714{
715 int len = 0;
716 while (list) {
717 len += list->len;
718 list = list->next;
719 }
720 return (len);
721}
722
723/* ListStrLen - ermittelt die Laenge einer Str-List als String */
724/* d.h. mit " am Anfang und Ende, sowie einem \ vor */
725/* jedem \ und " */
726int ListStrLen(struct strnode *list)
727{
728 int len = 2;
729 while (list) {
730 if (list->type == SPACE)
731 len++;
732 else {
733 len += list->len;
734 if (list->type == PP_STR && list->str[0] == '\"')
735 len += 2;
736 else if (list->type == NORMAL && list->str[0] == '\\')
737 len++;
738 }
739 list = list->next;
740 }
741 return (len);
742}
743
744/* CopyList2StrStr - kopiert eine Str-List als String um */
745/* d.h. mit " am Anfang und Ende, sowie einem \ vor */
746/* jedem \ und " */
747CopyList2StrStr(struct strnode * list, char *str)
748{
749 int len;
750
751 if (DEBUG & 32)
752 puts("CopyList2StrStr");
753
754
755 str[0] = 0;
756 if (list) {
757 strcpy(str, "\"");
758 len = 1;
759 while (list) {
760 if (list->type == SPACE) {
761 len++;
762 strcat(str, " ");
763 } else {
764 len += list->len;
765 if (list->type == PP_STR && list->str[0] == '\"') {
766 strcat(str, "\\");
767 strncat(str, list->str, list->len - 1);
768 strcat(str, "\\\"");
769 } else if (list->type == NORMAL && list->str[0] == '\\') {
770 strcat(str, "\\");
771 strcat(str, list->str);
772 } else
773 strcat(str, list->str);
774 }
775 list = list->next;
776 }
777 strcat(str, "\"");
778 len++;
779 }
780 return (len);
781}
782
783/* NextToSpecial - checked, ob die StrNode neben einem # oder ## steht */
784int NextToSpecial(struct strnode *node)
785{
786 struct strnode *search;
787
788 if (DEBUG & 32)
789 puts("NextToSpecial");
790
791
792 if (node->prev) {
793 search = node->prev;
794 while (search && search->type == SPACE)
795 search = search->prev;
796 if (search && search->type == SPECIAL)
797 return (search->flags);
798 }
799 if (node->next) {
800 search = node->next;
801 while (search && search->type == SPACE)
802 search = search->next;
803 /* Hinter der Node ist ein # (ToString) ohne Bedeutung */
804 if (search && search->type == SPECIAL
805 && search->flags == KILLSPACES)
806 return (KILLSPACES);
807 }
808 return (NONE);
809}
810
811/* FindBracket - sucht das passende Gegenstueck zu der (, auf die Node zeigt */
812/* dabei werden verschachtelte Klammern beachtet */
813struct strnode *FindBracket(struct strnode *node)
814{
815
816 if (DEBUG & 32)
817 puts("FindBracket");
818
819
820 if (node && node->next && node->type == NORMAL && node->str[0] == '(') {
821 do {
822 node = node->next;
823 if (node && node->type == NORMAL) {
824 if (node->str[0] == ')')
825 return (node);
826 if (node->str[0] == '(')
827 node = FindBracket(node);
828 }
829 } while (node);
830 return (NULL);
831 } else
832 return (NULL);
833}
834
835/* CloneArg - gibt eine Liste zurueck, die das n. Argument des Makros enthaelt */
836struct strnode *CloneArg(struct strnode *list, int n, int *error)
837{
838 int argnum = 0;
839 struct strnode *start;
840
841 if (error)
842 *error = OK;
843
844 if (list) {
845 if (DEBUG & 32)
846 printf("CloneArg\n");
847 if (list->type == PP_IDENT)
848 list = list->next;
849 while (list && list->type == SPACE)
850 list = list->next;
851
852 if (list && list->type == NORMAL && list->str[0] == '(') {
853 list = list->next; /* Skip ( */
854
855 if (DEBUG & 32)
856 printf("- IDENT skipped, ( found\n");
857
858 while (list && (argnum < n)) {
859 if (list->type == NORMAL) {
860 if (list->str[0] == ')')
861 list = NULL;
862 if (list && list->str[0] == '(')
863 list = (FindBracket(list))->next;
864 if (list && list->str[0] == ',')
865 argnum++;
866 }
867 if (list)
868 list = list->next;
869 }
870
871 while (list && list->type == SPACE)
872 list = list->next;
873
874 if (list) {
875 if (list->type == NORMAL && (list->str[0] == ')' || list->str[0] == ',')) { /* HIER evtl. ein Space erzeugen */
876 return (NULL);
877 }
878 start = list;
879 } else {
880 if (error)
881 *error = ARG_EXPECTED;
882 return (NULL);
883 }
884
885 if (DEBUG & 32)
886 printf("- Okay, Arg-Start found: %s\n", start->str);
887
888 while (list && (argnum == n)) {
889 if (list->type == NORMAL) {
890 switch (list->str[0]) {
891 case ')':
892 case ',':
893 argnum++;
894 list = list->prev;
895 break;
896 case '(':
897 list = FindBracket(list);
898 default:
899 if (list)
900 list = list->next;
901 break;
902 }
903 } else if (list)
904 list = list->next;
905 }
906
907 while (list && list->type == SPACE)
908 list = list->prev;
909
910 if (DEBUG & 32)
911 printf("- Okay, Arg-End found: %s\n", list->str);
912 return (CloneStrList(start, list));
913
914 } else {
915 if (error)
916 *error = ARG_EXPECTED;
917 return (NULL);
918 }
919 } else
920 return (NULL);
921}
922
923/* ExpandArgMakro - ersetzt ein Makro mit Argumenten */
924int ExpandArgMakro(struct mnode *makro, struct strnode **list,
925 struct strnode **pos)
926{
927 struct strnode *clone, *temp, *temp1, *arg, *new;
928 struct strnode *prev, *next;
929 struct mnode *prevmakro;
930 char *newstr;
931 int spec, len, x;
932
933 clone = CloneStrList(makro->tokenlist, NULL);
934 if (!clone)
935 return (OUT_OF_MEM);
936
937 if (DEBUG & 32)
938 printf("ExpandArgMakro - Clone build.\n");
939
940 temp = clone;
941 while (temp) {
942 if (temp->type == ARGUMENT) {
943 arg = CloneArg(*pos, temp->number, &x);
944 if (!arg) {
945 DelStrList(&clone);
946 return (x);
947 }
948 if (DEBUG & 32) {
949 printf("ARGUMENT:\n");
950 PrintTL(arg);
951 printf("Argument found - ");
952 }
953 if (spec = NextToSpecial(temp)) {
954 /* nicht expandieren, nur einsetzen */
955 if (spec == TOSTRING) {
956
957 if (DEBUG & 32)
958 printf("next to #\n");
959 /* als String einsetzen */
960 new = (struct strnode *) malloc(sizeof(struct strnode));
961 if (!new) {
962 DelStrList(&clone);
963 DelStrList(&arg);
964 return (OUT_OF_MEM);
965 }
966 len = ListStrLen(arg);
967 newstr = (char *) malloc(len + 1);
968 if (!newstr) {
969 DelStrList(&clone);
970 DelStrList(&arg);
971 if (new)
972 free(new);
973 return (OUT_OF_MEM);
974 }
975 CopyList2StrStr(arg, newstr);
976 DelStrList(&arg);
977 new->len = len + 2;
978 new->flags = new->number = 0;
979 new->type = PP_STR;
980 new->str = newstr;
981
982 prev = temp->prev;
983 next = temp->next;
984 DelStrNode(NULL, temp); /* Argument */
985
986 while (prev && prev->type == SPACE) {
987 temp = prev->prev;
988 DelStrNode(&clone, prev);
989 prev = temp;
990 }
991
992 if (prev && prev->type == SPECIAL && prev->flags == TOSTRING) {
993 temp = prev->prev;
994 DelStrNode(&clone, prev);
995 prev = temp;
996 } else
997 ierror(0);
998
999 new->prev = prev;
1000 if (prev)
1001 prev->next = new;
1002 else
1003 clone = new;
1004 new->next = next;
1005 if (next)
1006 next->prev = new;
1007 temp = new;
1008 } else {
1009 /* Einfach nur einsetzen */
1010 if (DEBUG & 32)
1011 printf("next to ##\n");
1012 prev = temp->prev;
1013 next = temp->next;
1014 DelStrNode(NULL, temp);
1015 arg->prev = prev;
1016 if (prev)
1017 prev->next = arg;
1018 else
1019 clone = arg;
1020 while (arg->next)
1021 arg = arg->next;
1022 arg->next = next;
1023 if (next)
1024 next->prev = arg;
1025 temp = arg;
1026 }
1027 } else {
1028 /* expandieren und einsetzen */
1029 if (DEBUG & 32)
1030 printf("normal arg\n");
1031 if (x = ExpandList(&arg)) {
1032 DelStrList(&clone);
1033 DelStrList(&arg);
1034 return (x);
1035 }
1036 if (DEBUG & 32) {
1037 printf("expanded arg:\n");
1038 PrintTL(arg);
1039 }
1040 prev = temp->prev;
1041 next = temp->next;
1042 DelStrNode(NULL, temp);
1043 arg->prev = prev;
1044 if (prev)
1045 prev->next = arg;
1046 else
1047 clone = arg;
1048 while (arg->next)
1049 arg = arg->next;
1050 arg->next = next;
1051 if (next)
1052 next->prev = arg;
1053 temp = arg;
1054 } /* of N2Special */
1055 }
1056 if (temp)
1057 temp = temp->next;
1058 }
1059
1060 if (DEBUG & 32)
1061 printf("Arguments expanded.\n");
1062
1063 temp = clone;
1064 while (temp) {
1065 if (temp->type == SPECIAL && temp->flags == KILLSPACES) {
1066 prev = temp->prev;
1067 next = temp->next;
1068 if ((prev->type == PP_IDENT || prev->type == NUMBER)) {
1069 switch (next->type) {
1070 case NUMBER: /* merge -> ident */
1071 case PP_IDENT:
1072 RemStrNode(&clone, next);
1073 MergeStrNodes(prev, next);
1074 next = temp->next;
1075 /* next will now be deleted and prev->str will be */
1076 /* the joined strings from prev&next */
1077 default: /* no merge / del ## */
1078 DelStrNode(&clone, temp);
1079 temp = next;
1080 break;
1081 } /* of switch */
1082 } else {
1083 DelStrNode(&clone, temp);
1084 temp = next;
1085 }
1086 }
1087 if (temp)
1088 temp = temp->next;
1089 }
1090
1091 /* 'makro' aus mlist ausklinken */
1092 prevmakro = makro->prev;
1093 RemMakroNode(&mlist, makro);
1094
1095 /* alles expandieren */
1096 if (!(x = ExpandList(&clone))) {
1097 /* akt. StrNode durch clone-Liste ersetzen */
1098
1099 if (DEBUG & 32) {
1100 printf("Complete Makro expanded\n");
1101 PrintTL(clone);
1102 }
1103 /* clone anstelle von pos in list einsetzen */
1104 prev = (*pos)->prev;
1105 next = (*pos)->next;
1106
1107 DelStrNode(NULL, *pos);
1108
1109#ifdef bla
1110 while (next && next->type == SPACE) {
1111 temp = next->next;
1112 DelStrNode(NULL, next); /* SPACE zwischen Makro und Args loeschen */
1113 next = temp;
1114 }
1115#endif
1116 while (next && next->type == SPACE)
1117 next = next->next;
1118 /* SPACE hinter Makro ueberspringen */
1119
1120 if (next && next->type == NORMAL && next->str[0] == '(') {
1121 temp = next;
1122 next = FindBracket(temp);
1123 if (next)
1124 next = next->next;
1125 do {
1126 temp1 = temp->next;
1127 DelStrNode(NULL, temp); /* ARG-List hinter Makro loeschen */
1128 temp = temp1;
1129 } while (temp != next);
1130 } else {
1131 ierror(0);
1132 }
1133
1134
1135 /* vor clone ein SPACE einsetzen, wenn nicht PREV==SPACE */
1136/*vb: hier !prev|| wegen Enforcerhit eingesetzt; waere prev&& besser? */
1137 if (!prev || prev->type != SPACE) {
1138 if (temp = AllocSpace()) {
1139 temp->next = clone;
1140 if (clone)
1141 clone->prev = temp;
1142 clone = temp;
1143 }
1144 }
1145 clone->prev = prev;
1146 if (prev)
1147 prev->next = clone;
1148 else
1149 *list = clone;
1150
1151 while (clone->next)
1152 clone = clone->next;
1153 /* nach clone ein SPACE einsetzen, wenn nicht NEXT==SPACE */
1154/*vb: hier !next|| wegen Enforcerhit eingesetzt; waere next&& besser? */
1155 if (!next || next->type != SPACE) {
1156 if (temp = AllocSpace()) {
1157 temp->prev = clone;
1158 if (clone)
1159 clone->next = temp;
1160 clone = temp;
1161 }
1162 }
1163 *pos = clone;
1164 clone->next = next;
1165 if (next)
1166 next->prev = clone;
1167
1168 /* 'makro' wieder einsetzen */
1169 InsertMakroNode(&mlist, makro, prevmakro);
1170 return (OK);
1171 } else {
1172 InsertMakroNode(&mlist, makro, prevmakro);
1173 return (x);
1174 }
1175
1176}
1177
1178/* ExpandList - ersetzt alle Makros in der Liste */
1179int ExpandList(struct strnode **list)
1180{
1181 struct mnode *found, *before;
1182 struct strnode *clone, *beforestr, *afterstr, *listtemp, *temp2,
1183 *temp3;
1184 int result = OK;
1185
1186 if (DEBUG & 32)
1187 puts("ExpandList");
1188
1189
1190 listtemp = *list;
1191 while (listtemp) {
1192
1193 if (listtemp->type == PP_IDENT) {
1194
1195 found = FindMakroNode(mlist, listtemp->str, 0);
1196 if (found) {
1197/*vb: merken, ob mind. ein Makro expandiert wurde */
1198 did_expand = 1;
1199 if (found->flags & PARAMETER) {
1200 /* Makro mit Argument(en) */
1201 if (DEBUG & 32)
1202 printf("Makro with args\n");
1203
1204 temp2 = listtemp->next;
1205 while (temp2 && temp2->type == SPACE)
1206 temp2 = temp2->next;
1207
1208 if (temp2 && temp2->type == NORMAL && temp2->str[0] == '(')
1209 if (result = ExpandArgMakro(found, list, &listtemp))
1210 return (result);
1211
1212 } else {
1213
1214 /* Makro ohne Argument */
1215
1216 /* ExpandNormMakro - expandiert ein Makro ohne Argumente */
1217 /* Parameter: s.o. */
1218
1219 if (found->flags & FUNCTION) {
1220 clone = DoMakroFunction(found);
1221 } else {
1222 clone = CloneStrList(found->tokenlist, NULL);
1223 }
1224 if (!clone)
1225 return (OUT_OF_MEM);
1226 /* akt. MakroNode ausklinken um rekursive Exp. zu verhindern */
1227 before = found->prev;
1228 RemMakroNode(&mlist, found);
1229 if (!(result = ExpandList(&clone))) {
1230 /* akt. StrNode durch clone-Liste ersetzen */
1231 beforestr = listtemp->prev;
1232 afterstr = listtemp->next;
1233 DelStrNode(NULL, listtemp);
1234 listtemp = afterstr;
1235 clone->prev = beforestr;
1236 if (beforestr)
1237 beforestr->next = clone;
1238 else
1239 *list = clone;
1240 while (clone->next)
1241 clone = clone->next;
1242 clone->next = afterstr;
1243 if (afterstr)
1244 afterstr->prev = clone;
1245 /* akt. Makronode wieder einsetzen */
1246 InsertMakroNode(&mlist, found, before);
1247 } else {
1248 /* akt. Makronode wieder einsetzen */
1249 InsertMakroNode(&mlist, found, before);
1250 return (result);
1251 }
1252 }
1253 }
1254 }
1255 if (listtemp)
1256 listtemp = listtemp->next;
1257 }
1258
1259 return (OK);
1260}
1261
1262
1263/* ParseIdentifier - parsed den Input-Define-String und haengt das Makro */
1264/* in die Liste */
1265
1266struct mnode *ParseIdentifier(char *str)
1267{
1268 int x, numargs = 0, flags = 0, len = 0;
1269 char *name = NULL, *args = NULL, *token = NULL, *temp, *temp2, *argtemp;
1270 struct mnode *newmakro, *found;
1271 struct strnode *tokenlist = NULL, *templist, *arglist = NULL, *templist2;
1272 struct strnode *next, *prev;
1273
1274 if (DEBUG & 32)
1275 puts("ParseIdentifier");
1276
1277/*vb: casts eingefuegt */
1278 while (isspace((unsigned char) *str)) {
1279 str++;
1280 }
1281 if (!(isalpha((unsigned char) *str) || *str == '_')) {
1282 error(178);
1283 return (0);
1284 }
1285 temp = str;
1286 while (isalnum((unsigned char) *temp) || (*temp == '_')) {
1287 temp++;
1288 len++;
1289 }
1290
1291 /* auf schon vorhandene (evtl. FESTE) Definition suchen */
1292 found = FindMakroNode(mlist, str, len);
1293 if (found && (found->flags & NOREDEF)) {
1294 error(179);
1295 return (0);
1296 }
1297/*vb: */
1298 if (1) {
1299 /* Okay, ist egal, wie das alte Makro aussah */
1300
1301/*vb: */
1302 if (found && !(c_flags[15] & USEDFLAG)) {
1303 error(197);
1304 }
1305 temp = name = (char *) malloc(len + 1); /* Speicher fuer Name-String belegen */
1306 if (!name) {
1307 error(196);
1308 return (0);
1309 }
1310 for (x = 0; x < len; x++) {
1311 *temp++ = *str++;
1312 } /* Namen kopieren */
1313 *temp = 0;
1314
1315 if (*str == '(') {
1316 flags |= PARAMETER;
1317 str++; /* jump over '(' */
1318 temp = str;
1319 len = 0;
1320/*vb: casts eingefuegt */
1321 while (*temp && (*temp != ')'))
1322 if (!(isspace((unsigned char) *temp))) {
1323 len++;
1324 temp++;
1325 } else {
1326 temp++;
1327 }
1328 if (*temp == 0) {
1329 error(180);
1330 if (name)
1331 free(name);
1332 return (0);
1333 }
1334 args = temp = (char *) malloc(len + 1);
1335 if (!args) {
1336 error(196);
1337 if (name)
1338 free(name);
1339 return (0);
1340 }
1341 for (x = 0; x < len;)
1342 if (!(isspace((unsigned char) *str))) {
1343 x++;
1344 *temp++ = *str++;
1345 } else {
1346 str++;
1347 }
1348 *temp = 0;
1349 str++; /* jump over ')' */
1350
1351 /* Argumentliste parsen und auf Fehler pruefen */
1352 temp = args;
1353 while (*temp && (isalpha((unsigned char) *temp) || *temp == '_')) {
1354 temp++;
1355 while (*temp && (isalnum((unsigned char) *temp) || *temp == '_')) {
1356 temp++;
1357 }
1358 if (!(*temp) || *temp == ',') {
1359 numargs++;
1360 if ((*temp == ',') && (isalpha((unsigned char) *(temp + 1)) || *(temp + 1) == '_'))
1361 temp++;
1362 }
1363 }
1364 if (*temp) {
1365 if (args)
1366 free(args);
1367 if (name)
1368 free(name);
1369 if (*temp == ',') {
1370 error(181);
1371 } else {
1372 error(182);
1373 }
1374 return (0);
1375 }
1376 }
1377 while (isspace((unsigned char) *str))
1378 str++; /* Skip Spaces */
1379 /* HIER: pruefen, ob tokenlist erstellt werden konnte (leere tokenlist->ok) */
1380 tokenlist = Str2List(str);
1381 if (DEBUG & 32)
1382 printf(" - build TokenList\n");
1383 templist = tokenlist;
1384 while (templist) {
1385 if ((templist->type == NORMAL) && (!strcmp(templist->str, "#"))) {
1386
1387 if ((templist->next) && (templist->next->type == NORMAL)
1388 && (!strcmp(templist->next->str, "#"))) {
1389 /* ## KILLSPACES */
1390 if ((templist->prev) && (templist->next->next)) {
1391 templist->type = SPECIAL;
1392 templist->flags = KILLSPACES;
1393 DelStrNode(&tokenlist, templist->next);
1394 } else {
1395 error(183);
1396 if (name)
1397 free(name);
1398 if (args)
1399 free(args);
1400 if (tokenlist)
1401 DelStrList(&tokenlist);
1402 return (0);
1403 }
1404 }
1405 }
1406 templist = templist->next;
1407 }
1408
1409 /* Token parsen/kopieren */
1410 if ((flags & PARAMETER)) { /* Argumente parsen */
1411 arglist = NULL;
1412 temp = temp2 = args;
1413 while (*temp) {
1414 len = 0;
1415 while (*temp && *temp != ',') {
1416 temp++;
1417 len++;
1418 }
1419 if (*temp == ',')
1420 temp++;
1421 argtemp = (char *) malloc(len + 1);
1422 if (!argtemp) {
1423 error(196);
1424 if (name)
1425 free(name);
1426 if (args)
1427 free(args);
1428 if (arglist)
1429 DelStrList(&arglist);
1430 if (tokenlist)
1431 DelStrList(&tokenlist);
1432 return (0);
1433 }
1434 strncpy(argtemp, temp2, len);
1435 temp2 = temp;
1436 *(argtemp + len) = 0;
1437 AddStrNodeBehind(&arglist, NULL, argtemp);
1438 }
1439 templist = tokenlist;
1440 while (templist) {
1441 if (templist->type == PP_IDENT) {
1442 x = 0;
1443 templist2 = arglist;
1444 while (templist2) {
1445 if (!strcmp(templist->str, templist2->str)) {
1446 templist->type = ARGUMENT;
1447 templist->number = x;
1448 }
1449 x++;
1450 templist2 = templist2->next;
1451 }
1452 }
1453 templist = templist->next;
1454 }
1455 DelStrList(&arglist);
1456 if (DEBUG & 32)
1457 printf(" - Arguments found.\n");
1458 /* #-Specials korrigieren, nachdem die Argumente erkannt wurden */
1459 templist = tokenlist;
1460 while (templist) {
1461 if ((templist->type == NORMAL) && (!strcmp(templist->str, "#"))) {
1462 if ((templist->next) && (templist->next->type == ARGUMENT)) {
1463 templist->type = SPECIAL;
1464 templist->flags = TOSTRING;
1465 } else {
1466 error(184);
1467 if (name)
1468 free(name);
1469 if (args)
1470 free(args);
1471 if (arglist)
1472 DelStrList(&arglist);
1473 if (tokenlist)
1474 DelStrList(&tokenlist);
1475 return (0);
1476 }
1477 }
1478 templist = templist->next;
1479 }
1480 if (DEBUG & 32)
1481 printf(" - Special-# corrected.\n");
1482 } else { /* Token kopieren */
1483 temp = str;
1484 len = 0;
1485 while ((*temp) && (*temp != '\n')) {
1486 temp++;
1487 len++;
1488 }
1489 temp = token = (char *) malloc(len + 1);
1490 if (!token) {
1491 error(196);
1492 if (name)
1493 free(name);
1494 if (args)
1495 free(args);
1496 if (tokenlist)
1497 DelStrList(&tokenlist);
1498 return (0);
1499 }
1500 for (x = 0; x < len; x++) {
1501 *temp++ = *str++;
1502 }
1503 *temp = 0;
1504 }
1505
1506
1507 templist = tokenlist;
1508 while (templist) {
1509 if (templist->type == SPECIAL && templist->flags == KILLSPACES) {
1510 next = templist->next;
1511 prev = templist->prev;
1512
1513 /* Kill Spaces before/after ## */
1514 while (prev && prev->type == SPACE) {
1515 templist2 = prev->prev;
1516 DelStrNode(&tokenlist, prev);
1517 prev = templist2;
1518 }
1519 while (next && next->type == SPACE) {
1520 templist2 = next->next;
1521 DelStrNode(&tokenlist, next);
1522 next = templist2;
1523 }
1524 if ((!next) || (!prev))
1525 ierror(0);
1526
1527 if (next->type != ARGUMENT && prev->type != ARGUMENT) {
1528 if ((prev->type == PP_IDENT || prev->type == NUMBER)) {
1529 switch (next->type) {
1530 case NUMBER: /* merge -> ident */
1531 case PP_IDENT:
1532 RemStrNode(&tokenlist, next);
1533 MergeStrNodes(prev, next);
1534 next = templist->next;
1535 /* next will now be deleted and prev->str will be */
1536 /* the joined strings from prev&next */
1537 default: /* no merge / del ## */
1538 DelStrNode(&tokenlist, templist);
1539 templist = next;
1540 break;
1541 } /* of switch */
1542 } else {
1543 DelStrNode(&tokenlist, templist);
1544 templist = next;
1545 }
1546 }
1547 }
1548 if (templist)
1549 templist = templist->next;
1550 }
1551
1552
1553/* erst HIER bei allowredefinition=0 abfragen ?? */
1554
1555 if (newmakro = (struct mnode *) malloc(sizeof(struct mnode))) {
1556 newmakro->name = name;
1557 newmakro->args = args;
1558 newmakro->token = token;
1559 newmakro->tokenlist = tokenlist;
1560 newmakro->flags = flags;
1561 newmakro->funcnum = 0;
1562 AddMakroNode(&mlist, newmakro);
1563 } else {
1564 error(196);
1565 if (name)
1566 free(name);
1567 if (token)
1568 free(token);
1569 if (args)
1570 free(args);
1571 if (tokenlist)
1572 DelStrList(&tokenlist);
1573 }
1574 return (newmakro);
1575
1576 } else {
1577/*vb: das ist irgendwie Unsinn hier, glaube ich */
1578 ierror(0);
1579 /* HIER: ueberpruefen, ob Macrodefinitionen uebereinstimmen, sonst Error */
1580 if (*temp == '(') {
1581 if (found->flags & PARAMETER) {
1582 temp++; /* skip ( */
1583
1584
1585
1586 } else {
1587 error(185);
1588 return (NULL);
1589 }
1590 }
1591 /* HIER nur noch tokenlisten vergleichen */
1592
1593 }
1594 if (DEBUG & 32)
1595 printf("ParseIdent falls of\n");
1596}
1597
1598
1599/* PreParse - 3-Zeichen-Folgen ersetzen, \+CR Zeilen anhaengen, usw.. */
1600
1601int PreParse()
1602{
1603 char *src, *dest, *dest2;
1604 int slen, dlen = 0;
1605 int cat = 0; /*vb: um zu merken, ob Zeilen mit \ verbunden werden */
1606 dest2 = string;
1607
1608 if (DEBUG & 32)
1609 puts("PreParse");
1610
1611
1612 if (!fgets(ppstring, MAXPPINPUT, in[incnesting])) {
1613 if (cmtnesting)
1614 error(186);
1615/*vb: */
1616/* if(ifstatus[incnesting]) error(186); */
1617/* ifnesting--; */
1618 if (DEBUG & 32)
1619 printf("-- end of file ifnesting-1:%d\n\n", incnesting);
1620 if (incnesting) {
1621 fclose(in[incnesting]);
1622 incnesting--;
1623 return (pp_nextline());
1624 } else
1625 return (0);
1626 } else if (DEBUG & 32)
1627 printf("gets1:%s\n", ppstring); /*vb: */
1628
1629 if ((strlen(ppstring) == (MAXPPINPUT - 1)) && (ppstring[MAXPPINPUT - 2] != '\n')) {
1630 error(177);
1631 return (0);
1632 }
1633 zn[incnesting]++;
1634 linenr = zn[incnesting];
1635
1636 do {
1637 /* Zeilen einlesen, bis kein Kommentar mehr */
1638
1639 /* Zeilen einlesen bis kein \ mehr am Ende */
1640 do {
1641 /* Source-String an Dest-String anhaengen und ??x-Folgen ersetzen */
1642/*vb: das killt sonst das angehaengte wieder */
1643 if (cat == 0) {
1644 dest = src = ppstring;
1645 slen = 0;
1646 }
1647 do {
1648 if (*src != '\n') {
1649
1650 if ((*src == '?') && (*(src + 1) == '?') && !(c_flags[16] & USEDFLAG)) {
1651 switch (*(src + 2)) {
1652 case '=':
1653 *dest++ = '#';
1654 src += 2;
1655 break;
1656 case '/':
1657 *dest++ = '\\';
1658 src += 2;
1659 break;
1660 case '\'':
1661 *dest++ = '^';
1662 src += 2;
1663 break;
1664 case '(':
1665 *dest++ = '[';
1666 src += 2;
1667 break;
1668 case ')':
1669 *dest++ = ']';
1670 src += 2;
1671 break;
1672 case '!':
1673 *dest++ = '|';
1674 src += 2;
1675 break;
1676 case '<':
1677 *dest++ = '{';
1678 src += 2;
1679 break;
1680 case '>':
1681 *dest++ = '}';
1682 src += 2;
1683 break;
1684 case '-':
1685 *dest++ = '~';
1686 src += 2;
1687 break;
1688 default:
1689 *dest++ = *src;
1690 break;
1691 } /* of switch */
1692 } else {
1693 *dest++ = *src;
1694 }
1695
1696 if (slen < MAXPPINPUT) {
1697 slen++;
1698 } else {
1699 error(177);
1700 return (0);
1701 }
1702 }
1703 } while (*src++);
1704
1705 src = dest;
1706 /* dest->lastchar+2/NULL+1 (dest-1)-> 0 (dest-2)->lastchar */
1707 if (*(dest - 2) == '\\') {
1708 /*vb: sollte das slen statt dlen sein? */
1709 if (fgets(src, MAXPPINPUT - dlen, in[incnesting])) {
1710 if (DEBUG & 32)
1711 printf("gets2:%s\n", src); /*vb: */
1712/* Hier auf LF+0 abfragen */
1713 dest -= 2;
1714 zn[incnesting]++;
1715 cat = 1; /*vb: merken, dass Zeilen verbunden wurden */
1716 }
1717 }
1718 } while (*dest == '\\');
1719
1720 src = ppstring;
1721 while (*src) {
1722 /* ' Strings ueberlesen */
1723 if ((*src == '\'') && (!cmtnesting)) {
1724 if (dlen < MAXINPUT) {
1725 *dest2++ = *src++;
1726 dlen++;
1727 } else {
1728 error(177);
1729 return (0);
1730 }
1731 while (*src && *src != '\'') {
1732 if (*src == '\\') {
1733 *dest2++ = *src++;
1734 dlen++;
1735 };
1736 if (dlen < MAXINPUT) {
1737 *dest2++ = *src++;
1738 dlen++;
1739 } else {
1740 error(177);
1741 return (0);
1742 }
1743 }
1744 if (dlen < MAXINPUT) {
1745 *dest2++ = *src++;
1746 dlen++;
1747 } else {
1748 error(177);
1749 return (0);
1750 }
1751 }
1752 /* " Strings ueberlesen */
1753 if ((*src == '\"') && (!cmtnesting)) {
1754 *dest2++ = *src++;
1755 dlen++;
1756 while (*src && *src != '\"') {
1757 if (*src == '\\') {
1758 *dest2++ = *src++;
1759 dlen++;
1760 };
1761 if (dlen < MAXINPUT) {
1762 *dest2++ = *src++;
1763 dlen++;
1764 } else {
1765 error(177);
1766 return (0);
1767 }
1768 }
1769 if (dlen < MAXINPUT) {
1770 *dest2++ = *src++;
1771 dlen++;
1772 } else {
1773 error(177);
1774 return (0);
1775 }
1776 }
1777 /* Kommentare weglassen */
1778 if ((*src == '/') && (*(src + 1) == '*')) {
1779 src += 2;
1780 if (dlen < MAXINPUT) {
1781 *dest2++ = ' ';
1782 dlen++;
1783 } else {
1784 error(177);
1785 return (0);
1786 }
1787 if ((cmtnesting && (c_flags[13] & USEDFLAG)) || (!cmtnesting))
1788 cmtnesting++;
1789 else
1790 error(198);
1791 } else {
1792 if ((*src == '*') && (*(src + 1) == '/') && cmtnesting) {
1793 src += 2;
1794 cmtnesting--;
1795 }
1796 }
1797
1798 /* C++-Comment weglassen */
1799 if ((!cmtnesting) && (*src == '/') && (*(src + 1) == '/') && (c_flags[14] & USEDFLAG))
1800 *src = 0;
1801
1802 if (!cmtnesting) {
1803 if (*src) {
1804 *dest2++ = *src++;
1805 }
1806 if (dlen < MAXINPUT) {
1807 dlen++;
1808 } else {
1809 error(177);
1810 return (0);
1811 }
1812 } else {
1813 if (*src)
1814 src++;
1815 }
1816 }
1817
1818 if (cmtnesting) {
1819 if (!fgets(ppstring, MAXPPINPUT, in[incnesting])) {
1820 if (cmtnesting)
1821 error(186);
1822 if (incnesting) {
1823 fclose(in[incnesting]);
1824 incnesting--;
1825 return (pp_nextline());
1826 } else
1827 return (0);
1828 } else if (DEBUG & 32)
1829 printf("gets2:%s\n", ppstring); /*vb: */
1830
1831 if ((strlen(ppstring) == (MAXPPINPUT - 1)) && (ppstring[MAXPPINPUT - 2] != '\n')) {
1832 error(177);
1833 return (0);
1834 }
1835 zn[incnesting]++;
1836 }
1837 } while (cmtnesting);
1838
1839/*vb: das ueberschreibt den Speicher */
1840#if 0
1841 *dest2-- = 0;
1842 while (isspace(*dest2))
1843 *dest2-- = 0; /* Spaces killen */
1844#endif
1845
1846/*vb: hoffe, das ist besser */
1847 *dest2 = 0;
1848 while (dest2 > string && isspace((unsigned char) *--dest2))
1849 *dest2 = 0;
1850
1851
1852 return (1);
1853}
1854
1855/* **************** PreProcessor ***************** */
1856
1857int pp_init(void)
1858{
1859 char *macroname;
1860 struct mnode *macronode;
1861
1862 if (!(c_flags[6] & USEDFLAG))
1863 printf("%s\n", pp_version);
1864
1865 incnesting = /*ifnesting= */ -1; /*vb: */
1866 cmtnesting = if_cnt = abs_if_cnt = 0;
1867 mlist = NULL;
1868 strlist = NULL;
1869
1870 macroname = (char *) malloc(9);
1871 if (!macroname)
1872 return (0);
1873 strcpy(macroname, "__LINE__");
1874 macronode = (struct mnode *) malloc(sizeof(struct mnode));
1875 if (!macronode) {
1876 if (macroname)
1877 free(macroname);
1878 return (0);
1879 }
1880 macronode->name = macroname;
1881 macronode->args = macronode->token = NULL;
1882 macronode->tokenlist = NULL;
1883 macronode->flags = FUNCTION | NODELETE | NOREDEF;
1884 macronode->funcnum = FUNCLINE;
1885 AddMakroNode(&mlist, macronode);
1886
1887 macroname = (char *) malloc(9);
1888 if (!macroname)
1889 return (0);
1890 strcpy(macroname, "__FILE__");
1891 macronode = (struct mnode *) malloc(sizeof(struct mnode));
1892 if (!macronode) {
1893 if (macroname)
1894 free(macroname);
1895 DelMakroList(&mlist);
1896 return (0);
1897 }
1898 macronode->name = macroname;
1899 macronode->args = macronode->token = NULL;
1900 macronode->tokenlist = NULL;
1901 macronode->flags = FUNCTION | NODELETE | NOREDEF;
1902 macronode->funcnum = FUNCFILE;
1903 AddMakroNode(&mlist, macronode);
1904
1905 macroname = (char *) malloc(9);
1906 if (!macroname)
1907 return (0);
1908 strcpy(macroname, "__DATE__");
1909 macronode = (struct mnode *) malloc(sizeof(struct mnode));
1910 if (!macronode) {
1911 if (macroname)
1912 free(macroname);
1913 DelMakroList(&mlist);
1914 return (0);
1915 }
1916 macronode->name = macroname;
1917 macronode->args = macronode->token = NULL;
1918 macronode->tokenlist = NULL;
1919 macronode->flags = FUNCTION | NODELETE | NOREDEF;
1920 macronode->funcnum = FUNCDATE;
1921 AddMakroNode(&mlist, macronode);
1922
1923 macroname = (char *) malloc(9);
1924 if (!macroname)
1925 return (0);
1926 strcpy(macroname, "__TIME__");
1927 macronode = (struct mnode *) malloc(sizeof(struct mnode));
1928 if (!macronode) {
1929 if (macroname)
1930 free(macroname);
1931 DelMakroList(&mlist);
1932 return (0);
1933 }
1934 macronode->name = macroname;
1935 macronode->args = macronode->token = NULL;
1936 macronode->tokenlist = NULL;
1937 macronode->flags = FUNCTION | NODELETE | NOREDEF;
1938 macronode->funcnum = FUNCTIME;
1939 AddMakroNode(&mlist, macronode);
1940
1941 macroname = (char *) malloc(9);
1942 if (!macroname)
1943 return (0);
1944 strcpy(macroname, "__STDC__");
1945 macronode = (struct mnode *) malloc(sizeof(struct mnode));
1946 if (!macronode) {
1947 if (macroname)
1948 free(macroname);
1949 DelMakroList(&mlist);
1950 return (0);
1951 }
1952 macronode->name = macroname;
1953 macronode->args = NULL;
1954 macroname = (char *) malloc(2);
1955 if (!macroname) {
1956 if (macronode->name)
1957 free(macronode->name);
1958 if (macronode)
1959 free(macronode);
1960 DelMakroList(&mlist);
1961 return (0);
1962 }
1963 strcpy(macroname, "1");
1964 macronode->token = macroname;
1965 macronode->tokenlist = Str2List(macroname);
1966 if (!macronode->tokenlist) {
1967 if (macronode->name)
1968 free(macronode->name);
1969 if (macronode->token)
1970 free(macronode->token);
1971 if (macronode)
1972 free(macronode);
1973 DelMakroList(&mlist);
1974 return (0);
1975 }
1976 macronode->flags = NODELETE;
1977 macronode->funcnum = 0;
1978 AddMakroNode(&mlist, macronode);
1979
1980 return (1);
1981}
1982
1983
1984void pp_free(void)
1985{
1986 int i;
1987
1988 if (DEBUG & 32)
1989 puts("pp_free");
1990
1991/*vb: Schleifenindex korrekt gesetzt */
1992 for (i = incnesting; i >= 0; i--)
1993 if (in[i])
1994 fclose(in[i]);
1995 DelMakroList(&mlist);
1996 DelStrList(&strlist);
1997}
1998
1999int pp_include(char *f)
2000{
2001 if (DEBUG & 32)
2002 printf("trying to include %s\n", f); /*vb: */
2003
2004 if (incnesting >= MAXINCNESTING - 1) {
2005 error(187);
2006 return (0);
2007 }
2008/*vb: */
2009/* if(ifnesting>=MAXIFNESTING-1) {error("Too many nested #ifs or #includes",0);return(0);} */
2010 incnesting++;
2011 /* ifnesting++; *//*vb: */
2012 ifstatus[incnesting] = 0; /*vb: */
2013
2014 if (DEBUG & 32)
2015 printf("-- include: ifnesting:%d ifstatus:0 \n\n", incnesting);
2016
2017 in[incnesting] = fopen(f, "r");
2018 if (!in[incnesting]) {
2019 incnesting--;
2020 return (0);
2021 }
2022 filenames[incnesting] = f;
2023 zn[incnesting] = linenr = 0;
2024 return (1);
2025}
2026
2027
2028
2029/* ********************** Main-Function ******************* */
2030int pp_nextline(void)
2031{
2032 char *src, *dest, *temp;
2033 int complete_len, len, i, result;
2034 struct mnode *makro;
2035 struct strnode *linelist, *inclinelist;
2036
2037 if (DEBUG & 32)
2038 puts("pp_nextline");
2039
2040 dest = string;
2041 dest[0] = 0;
2042
2043 /* String vorbereiten, 3ZF ersetzen, \-Zeilen anhaengen, Kommentare loeschen */
2044 if (!PreParse())
2045 return (0);
2046
2047 /* Ueberpruefung auf PreProcessor-Commands */
2048 src = string;
2049/*vb: casts eingefuegt */
2050 while (isspace((unsigned char) *src)) {
2051 src++;
2052 } /* SkipSpaces */
2053
2054 if (*src == '#') { /* #-Direktive gefunden */
2055 src++; /* # ueberlesen */
2056
2057 while (isspace((unsigned char) *src)) {
2058 src++;
2059 } /* SkipSpaces */
2060
2061/*vb: Direktiven, die nichts mit #if etc. zu tun haben, nach hinten */
2062
2063
2064/* IFDEF */
2065 if (!strncmp(src, "ifdef", 5)) {
2066 src += 5;
2067 abs_if_cnt++; /*vb: */
2068 if (isspace((unsigned char) *src)) {
2069 while (isspace((unsigned char) *src)) {
2070 src++;
2071 }
2072 /* identifier suchen */
2073 if (do_output) {
2074/*vb: */
2075/* if(ifnesting>=MAXIFNESTING-1) {error("Too many nested #if's",0); return(0);} */
2076/* ifnesting++; */
2077 temp = src;
2078 len = 0;
2079 while ((isalnum((unsigned char) *temp)) || (*temp == '_')) {
2080 temp++;
2081 len++;
2082 }
2083 makro = FindMakroNode(mlist, src, len);
2084 if (DEBUG & 32)
2085 printf("-- #ifdef found, ");
2086 if (makro) {
2087/*vb: */
2088 ifstatus[incnesting] = 1; /* Bedingung == TRUE */
2089 if (DEBUG & 32)
2090 printf(" condition '%s' found (TRUE)\n", makro->name);
2091 } else {
2092/*vb: */
2093 ifstatus[incnesting] = 2; /* Bedingung == FALSE */
2094 do_output = 0;
2095 if (DEBUG & 32)
2096 printf(" condition not found (FALSE)\n\n");
2097 }
2098 } else {
2099 if_cnt++;
2100 if (DEBUG & 32)
2101 printf("-- #ifdef found and if_cnt increased\n\n");
2102 }
2103 string[0] = 0; /*vb: yo */
2104 return (1);
2105 }
2106 } /* EO IFDEF */
2107 /* IFNDEF */
2108 if (!strncmp(src, "ifndef", 6)) {
2109 src += 6;
2110 abs_if_cnt++; /*vb: */
2111 if (isspace((unsigned char) *src)) {
2112 while (isspace((unsigned char) *src)) {
2113 src++;
2114 }
2115
2116 /* identifier suchen */
2117 if (do_output) {
2118/*vb: */
2119/* if(ifnesting>=MAXIFNESTING-1) {error("Too many nested #if's",0); return(0);} */
2120/* ifnesting++; */
2121 temp = src;
2122 len = 0;
2123 while ((isalnum((unsigned char) *temp)) || (*temp == '_')) {
2124 temp++;
2125 len++;
2126 }
2127 if (DEBUG & 32)
2128 printf("-- FindMakroNode: len=%d temp=%p\n", len, (void*)temp);
2129 makro = FindMakroNode(mlist, src, len);
2130 if (DEBUG & 32)
2131 printf("-- #ifndef found, ");
2132 if (!makro) {
2133/*vb: */
2134 ifstatus[incnesting] = 1; /* Bedingung == TRUE (Makro not existing) */
2135 if (DEBUG & 32)
2136 printf(" condition not found (TRUE)\n\n");
2137 } else {
2138/*vb: */
2139 ifstatus[incnesting] = 2; /* Bedingung == FALSE */
2140 do_output = 0;
2141 if (DEBUG & 32)
2142 printf(" condition '%s' found (FALSE)\n\n", makro->name);
2143 }
2144 /* HIER: string[0]=0; */
2145 } else {
2146 if_cnt++;
2147 if (DEBUG & 32)
2148 printf("-- #ifndef found and if_cnt increased\n\n");
2149 }
2150 string[0] = 0; /*vb: */
2151 return (1);
2152 }
2153 } /* EO IFNDEF */
2154 /* IF */
2155 if (!strncmp(src, "if", 2)) {
2156 src += 2;
2157 abs_if_cnt++; /*vb: */
2158 if (isspace((unsigned char) *src)) {
2159 while (isspace((unsigned char) *src)) {
2160 src++;
2161 }
2162 /* Bedingung auswerten */
2163
2164
2165
2166 printf("****** WARNING ******* #if is not yet implemented\n");
2167
2168
2169 string[0] = 0; /*vb: */
2170 return (1);
2171 }
2172 } /* EO IF */
2173 /* ELIF */
2174 if (!strncmp(src, "elif", 4)) {
2175 src += 4;
2176 if (isspace((unsigned char) *src)) {
2177 while (isspace((unsigned char) *src)) {
2178 src++;
2179 }
2180 /* Bedingung auswerten */
2181
2182
2183
2184
2185
2186 printf("****** WARNING ******* #elif is not yet implemented\n");
2187
2188
2189
2190
2191 string[0] = 0; /*vb: */
2192 return (1);
2193 }
2194 } /* EO ELIF */
2195 /* ELSE */
2196 if (!strncmp(src, "else", 4)) {
2197 src += 4;
2198 if (isspace((unsigned char) *src) || *src == 0) {
2199 while (isspace((unsigned char) *src)) {
2200 src++;
2201 }
2202
2203 if (!if_cnt) {
2204 switch (ifstatus[incnesting]) { /*vb: */
2205 case 0:
2206 error(188);
2207 return (0);
2208 break;
2209 case 1:
2210 do_output = 0;
2211 /* HIER: auf #endif suchen SearchENDIF(); */
2212 /* HIER: ifnesting--; do_output=1; */
2213 break;
2214 case 2:
2215 ifstatus[incnesting] = 3; /*vb: */
2216 do_output = 1;
2217 break;
2218 case 3:
2219 error(189);
2220 return (0);
2221 break;
2222 }
2223 }
2224 string[0] = 0; /*vb: */
2225 return (1);
2226 }
2227 } /* EO ELSE */
2228 /* ENDIF */
2229 if (!strncmp(src, "endif", 5)) {
2230 src += 5;
2231 abs_if_cnt--; /*vb: */
2232 if (isspace((unsigned char) *src) || *src == 0) {
2233 while (isspace((unsigned char) *src)) {
2234 src++;
2235 }
2236 /* HIER: Auf Zeilenende testen */
2237
2238 if (DEBUG & 32)
2239 printf("-- #endif found, ");
2240
2241 if (if_cnt) {
2242 if_cnt--;
2243 if (DEBUG & 32)
2244 printf("if_cnt decreased (to %d)\n", if_cnt);
2245 } else {
2246 if (DEBUG & 32)
2247 printf("ifnesting: %d ifstatus: %d\n", incnesting, ifstatus[incnesting]);
2248 if (abs_if_cnt < 0 /*(incnesting==-1)||ifstatus[incnesting]==0 */ ) { /*vb: */
2249 error(190);
2250 return (0);
2251 }
2252 /* ifnesting--; *//*vb: */
2253 /* HIER: evtl. do_output entsprechend ifstatus[] setzen */
2254 /*vb: natuerlich */
2255 do_output = 1;
2256 ifstatus[incnesting] = abs_if_cnt > 0; /*vb: 1 oder 0 */
2257 }
2258 string[0] = 0; /*vb: ja */
2259 return (1);
2260 }
2261 } /* EO ENDIF */
2262 /*vb: andere Direktiven gegebenenfalls ueberspringen */
2263 if (!do_output) {
2264 if (DEBUG & 32)
2265 printf("do_output==0 => skipping: %s\n", src);
2266 string[0] = 0;
2267 return (1);
2268 }
2269/* DEFINE */
2270 if ( /*(do_output)&& */ (!strncmp(src, "define", 6))) { /*vb: */
2271 if (DEBUG & 32)
2272 printf("#define found\n");
2273 src += 6;
2274 if (isspace((unsigned char) *src)) {
2275 while (isspace((unsigned char) *src)) {
2276 src++;
2277 }
2278 if (ParseIdentifier(src)) {
2279 string[0] = 0;
2280 return (1);
2281 } else {
2282 if (DEBUG & 32)
2283 printf("ParseIdent returned 0\n");
2284 return (0);
2285 }
2286 }
2287 } /* EO DEFINE */
2288 /* UNDEF */
2289 if ( /*(do_output)&& */ (!strncmp(src, "undef", 5))) { /*vb: */
2290 src += 5;
2291 if (isspace((unsigned char) *src)) {
2292 while (isspace((unsigned char) *src)) {
2293 src++;
2294 }
2295 temp = src;
2296 len = 0;
2297 while ((isalnum((unsigned char) *temp)) || (*temp == '_')) {
2298 temp++;
2299 len++;
2300 }
2301 makro = FindMakroNode(mlist, src, len);
2302 if (makro->flags & NODELETE) {
2303 error(199);
2304 } else {
2305 DelMakroNode(&mlist, makro);
2306 }
2307 while (isspace((unsigned char) *temp)) {
2308 temp++;
2309 }
2310 if (*temp != 0 && *temp != '\n') {
2311 error(200);
2312 }
2313 string[0] = 0;
2314 return (1);
2315 }
2316 } /* EO UNDEF */
2317 /* INCLUDE */
2318 if ( /*(do_output)&& */ (!strncmp(src, "include", 7))) { /*vb: */
2319 src += 7;
2320 if (isspace((unsigned char) *src)) {
2321 while (isspace((unsigned char) *src)) {
2322 src++;
2323 }
2324 if (*src != '<' && *src != '\"') {
2325 /* Versuchen den Rest zu expandieren */
2326 inclinelist = Str2List(src);
2327 if (!ExpandList(&inclinelist)) {
2328 if (List2Str(inclinelist, src, MAXINPUT - (src - string))) {
2329 /* HIER exit ? */
2330 }
2331 } else {
2332 error(191); /* HIER exit ? */
2333 }
2334 }
2335/*vb: geaendert, so dass #include "..." auch noch im Standardpfad sucht */
2336 if (DEBUG & 32)
2337 printf("includename=%s\n", src);
2338 if (*src == '<' || *src == '\"') {
2339 char *m = src, c;
2340 if (*src == '<')
2341 c = '>';
2342 else
2343 c = '\"';
2344 if (*src == '\"') {
2345 /* im aktuellen Verzeichnis suchen und includen */
2346 src++;
2347 temp = src;
2348 len = 0;
2349 while (*temp != '\"') {
2350 temp++;
2351 len++;
2352 }
2353 temp++;
2354 while (isspace((unsigned char) *temp))
2355 temp++;
2356 if (*temp) {
2357 error(200);
2358 }
2359 temp = (char *) malloc(len + 1);
2360 if (temp) {
2361 strncpy(temp, src, len);
2362 *(temp + len) = 0;
2363 if (pp_include(temp)) {
2364 AddStrNode(&strlist, NULL, temp);
2365 string[0] = 0;
2366 return (1);
2367 } else {
2368 if (temp)
2369 free(temp);
2370/*vb:
2371 error("pp: cannot open file to include",0);
2372 return(0); */
2373 }
2374 } else {
2375 error(196);
2376 } /* HIER: Exit? */
2377 }
2378 /* in den Standard-Verzeichnissen suchen und includen */
2379 src = m;
2380 src++;
2381 temp = src;
2382 len = 0;
2383 while (*temp != c && *temp != 0) {
2384 temp++;
2385 len++;
2386 } /*vb: sicherer */
2387 temp++;
2388 while (isspace((unsigned char) *temp))
2389 temp++;
2390 if (*temp) {
2391 error(200);
2392 }
2393 temp = NULL;
2394 for (i = 0; i < incpathc; i++) {
2395 complete_len = strlen(incpath[i]) + len;
2396 temp = (char *) malloc(complete_len + 1);
2397 if (temp) {
2398 strcpy(temp, incpath[i]);
2399 strncat(temp, src, len);
2400 *(temp + complete_len) = 0;
2401 if (pp_include(temp)) {
2402 AddStrNode(&strlist, NULL, temp);
2403 if (DEBUG & 32)
2404 printf("include <%s> found\n", temp);
2405 string[0] = 0;
2406 return (1);
2407 } else {
2408 if (temp)
2409 free(temp);
2410 }
2411 } else {
2412 error(196);
2413 } /* HIER: Exit ? */
2414 } /* of FOR i */
2415 error(191);
2416 return (0);
2417 } else {
2418 error(192);
2419 return (0);
2420 }
2421 } else {
2422 error(193);
2423 return (0);
2424 }
2425 } /* EO INCLUDE */
2426 /* LINE */
2427 if (!strncmp(src, "line", 4)) {
2428 src += 4;
2429 if (isspace((unsigned char) *src)) {
2430 return (1); /* Ignorieren und an Compiler weiterreichen */
2431 }
2432 } /* EO LINE */
2433 /* ERROR */
2434 if (!strncmp(src, "error", 5)) {
2435 src += 5;
2436 if (isspace((unsigned char) *src)) {
2437 while (isspace((unsigned char) *src)) {
2438 src++;
2439 }
2440
2441 return (1);
2442 }
2443 } /* EO ERROR */
2444 /* PRAGMA */
2445 if (!strncmp(src, "pragma", 6)) {
2446 src += 6;
2447 if (isspace((unsigned char) *src)) {
2448 while (isspace((unsigned char) *src)) {
2449 src++;
2450 }
2451
2452 return (1);
2453 }
2454 } /* EO PRAGMA */
2455 /* Unknown */
2456 /* if(do_output){ */
2457 /*vb: */
2458 error(193);
2459 return (0);
2460 /* } *//*vb: */
2461 } else if (do_output) {
2462 /* Normale Anweisung. Komplette Zeile expandieren */
2463
2464/*vb: */
2465
2466 linelist = Str2List(string);
2467
2468 if (DEBUG & 32)
2469 PrintTL(linelist);
2470
2471/*vb: */
2472 did_expand = 0;
2473
2474 if (result = ExpandList(&linelist)) {
2475 switch (result) {
2476 case OUT_OF_MEM:
2477 error(196);
2478 break;
2479 case NUM_OF_ARGS:
2480 error(194);
2481 break;
2482 case ARG_EXPECTED:
2483 error(195);
2484 break;
2485 default:
2486 ierror(0);
2487 break;
2488 }
2489 DelStrList(&linelist);
2490 return (0);
2491 }
2492 if (DEBUG & 32)
2493 PrintTL(linelist);
2494
2495/*vb: List2Str nur aufrufen, falls etwas expandiert wurde */
2496 if (did_expand && !List2Str(linelist, string, MAXINPUT)) {
2497 DelStrList(&linelist);
2498 return (0);
2499 }
2500 DelStrList(&linelist);
2501
2502/*vb: */
2503 } else
2504 string[0] = 0;
2505 return (1);
2506}