]> gcc.gnu.org Git - gcc.git/blob - gcc/m2/tools-src/mklink.c
Remove unused parameter warning via introducing attribute unused.
[gcc.git] / gcc / m2 / tools-src / mklink.c
1 /* mklink.c creates startup code and the link command line.
2
3 Copyright (C) 2000-2022 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
5
6 This file is part of GNU Modula-2.
7
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22
23 #include "config.h"
24 #include "system.h"
25
26 #define MAX_FILE_NAME 8192
27 #define MAXSTACK 4096
28 #define STDIN 0
29 #define STDOUT 1
30 #define ENDOFILE ((char)-1)
31 #define ERROR(X) \
32 (fprintf (stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) \
33 && (fflush (stderr)))
34 #define DEBUG(X) \
35 ((Debug) && (fprintf (stderr, "%s\n", X) && (fflush (stderr))))
36
37 #if !defined(TRUE)
38 #define TRUE (1 == 1)
39 #endif
40
41 #if !defined(FALSE)
42 #define FALSE (1 == 0)
43 #endif
44
45 typedef struct functlist
46 {
47 char *functname;
48 struct functlist *next;
49 } functList;
50
51 /* Prototypes. */
52
53 static void ParseFileLinkCommand (void);
54 static void ParseFileStartup (void);
55 static void ParseFile (char *Name);
56 static void ParseComments (void);
57 static void CopyUntilEof (void);
58 static void CopyUntilEol (void);
59 static int IsSym (char *s);
60 static int SymIs (char *s);
61 static int FindString (char *String);
62 static void GetNL (void);
63 static char GetChar (void);
64 static void ResetBuffer (void);
65 static int GetSingleChar (char *ch);
66 static int InRange (int Element, unsigned int Min, unsigned int Max);
67 static char PutChar (char ch);
68 static int IsSpace (char ch);
69 static void SkipSpaces (void);
70 static void SkipText (void);
71 static void SilentSkipSpaces (void);
72 static void SilentSkipText (void);
73 static void PushBack (char *s);
74 static int IsDigit (char ch);
75 static void GetName (char *Name);
76 static void OpenOutputFile (void);
77 static void CloseFile (void);
78 static void FindSource (char *Name);
79 static void CopyUntilEolInto (char *Buffer);
80 static void FindObject (char *Name);
81 static int IsExists (char *Name);
82
83 /* Global variables. */
84
85 static char *NameOfFile = NULL;
86 static const char *NameOfMain = "main";
87 static int StackPtr = 0;
88 static char Stack[MAXSTACK];
89 static int CurrentFile = STDIN;
90 static int OutputFile;
91 static int LinkCommandLine = FALSE;
92 static int ProfilePCommand = FALSE;
93 static int ProfilePGCommand = FALSE;
94 static int ExitNeeded = TRUE;
95 static char *libraries = NULL;
96 static char *args = NULL;
97 static functList *head = NULL;
98 static functList *tail = NULL;
99 static int langC = FALSE; /* FALSE = C++, TRUE = C. */
100
101 /* addLibrary - adds libname to the list of libraries to be linked. */
102
103 static void
104 addLibrary (char *libname)
105 {
106 if (libraries == NULL)
107 libraries = strdup (libname);
108 else
109 {
110 char *old = libraries;
111 char *newlib
112 = (char *)malloc (strlen (libname) + strlen (libraries) + 1 + 1);
113 strcpy (newlib, libraries);
114 strcat (newlib, " ");
115 strcat (newlib, libname);
116 libraries = newlib;
117 free (old);
118 }
119 }
120
121 /* addGccArg - adds arg to the list of gcc arguments. */
122
123 static void
124 addGccArg (char *arg)
125 {
126 if (args == NULL)
127 args = strdup (arg);
128 else
129 {
130 char *old = args;
131 char *newarg = (char *)malloc (strlen (old) + strlen (arg) + 1 + 1);
132 strcpy (newarg, old);
133 strcat (newarg, " ");
134 strcat (newarg, arg);
135 args = newarg;
136 free (old);
137 }
138 }
139
140 int
141 main (int argc, char *argv[])
142 {
143 int i;
144
145 if (argc >= 3)
146 {
147 if (strcmp (argv[1], "-l") == 0)
148 LinkCommandLine = TRUE;
149 else if (strcmp (argv[1], "-s") == 0)
150 LinkCommandLine = FALSE;
151 else
152 {
153 fprintf (stderr, "Usage: mklink (-l|-s) [--langc|--langc++] [--pg|-p] "
154 "[--lib library] [--main name] [--exit] --name "
155 "filename <modulelistfile>\n");
156 fprintf (stderr, " must supply -l or -s option\n");
157 exit (1);
158 }
159 ProfilePCommand = FALSE;
160 ProfilePGCommand = FALSE;
161 i = 2;
162 while (i < argc - 1)
163 {
164 if (strcmp (argv[i], "--langc++") == 0)
165 langC = FALSE;
166 else if (strcmp (argv[i], "--langc") == 0)
167 langC = TRUE;
168 else if (strncmp (argv[i], "-f", 2) == 0)
169 addGccArg (argv[i]);
170 else if (strcmp (argv[i], "--pg") == 0)
171 ProfilePGCommand = TRUE;
172 else if (strcmp (argv[i], "-p") == 0)
173 ProfilePCommand = TRUE;
174 else if (strcmp (argv[i], "--exit") == 0)
175 ExitNeeded = FALSE;
176 else if (strcmp (argv[i], "--lib") == 0)
177 {
178 i++;
179 addLibrary (argv[i]);
180 }
181 else if (strcmp (argv[i], "--main") == 0)
182 {
183 i++;
184 NameOfMain = argv[i];
185 }
186 else if (strcmp (argv[i], "--name") == 0)
187 {
188 i++;
189 NameOfFile = argv[i];
190 }
191 i++;
192 }
193 ParseFile (argv[i]);
194 }
195 else
196 {
197 fprintf (stderr, "Usage: mklink (-l|-s) [--gcc|--g++] [--pg|-p] [--lib "
198 "library] [--main name] [--exit] --name filename "
199 "<modulelistfile>\n");
200 exit (1);
201 }
202 if (NameOfFile == NULL)
203 {
204 fprintf (stderr, "mklink must have a --name argument\n");
205 fprintf (stderr, "Usage: mklink (-l|-s) [--gcc|--g++] [--pg|-p] [--lib "
206 "library] [--main name] [--exit] --name filename "
207 "<modulelistfile>\n");
208 exit (1);
209 }
210 exit (0);
211 }
212
213 /* ParseFile - parses the input file and generates the output file. */
214
215 static void
216 ParseFile (char *Name)
217 {
218 FindSource (Name);
219 OpenOutputFile ();
220 if (LinkCommandLine)
221 ParseFileLinkCommand ();
222 else
223 ParseFileStartup ();
224 CloseFile ();
225 }
226
227 /* ParseFileLinkCommand - generates the link command. */
228
229 static void
230 ParseFileLinkCommand (void)
231 {
232 char name[MAX_FILE_NAME];
233 char *s = NULL;
234 char *l = NULL;
235 char *c = NULL;
236
237 s = getenv ("CC");
238 if (s == NULL)
239 {
240 if (langC)
241 printf ("gcc -g ");
242 else
243 printf ("g++ -g ");
244 }
245 else
246 printf ("%s -g ", s);
247
248 if (args != NULL)
249 printf ("%s ", args);
250
251 l = getenv ("LDFLAGS");
252 if (l != NULL)
253 printf ("%s ", l);
254
255 c = getenv ("CFLAGS");
256 if (c != NULL)
257 printf ("%s ", c);
258
259 if (ProfilePGCommand)
260 printf (" -pg");
261 else if (ProfilePCommand)
262 printf (" -p");
263
264 while (PutChar (GetChar ()) != (char)EOF)
265 {
266 CopyUntilEolInto (name);
267 #if defined(XENIX)
268 name[10] = (char)0; /* truncate object file name. */
269 #endif
270 if ((strlen (name) > 0) && (name[0] != '#'))
271 FindObject (name);
272 }
273 printf (" %s\n", libraries);
274 }
275
276 /* FindObject - searches the M2PATH variable to find the object file.
277 If it finds the object file it prints it to stdout otherwise it
278 writes an error on stderr. */
279
280 static void
281 FindObject (char *Name)
282 {
283 char m2search[4096];
284 char m2path[4096];
285 char name[4096];
286 char exist[4096];
287 int s, p;
288
289 if (getenv ("M2PATH") == NULL)
290 strcpy (m2path, ".");
291 else
292 strcpy (m2path, getenv ("M2PATH"));
293
294 snprintf (name, sizeof (name), "%s.o", Name);
295 p = 0;
296 while (m2path[p] != (char)0)
297 {
298 s = 0;
299 while ((m2path[p] != (char)0) && (m2path[p] != ' '))
300 {
301 m2search[s] = m2path[p];
302 s++;
303 p++;
304 }
305 if (m2path[p] == ' ')
306 p++;
307 m2search[s] = (char)0;
308 snprintf (exist, sizeof (exist), "%s/%s", m2search, name);
309 if (IsExists (exist))
310 {
311 printf (" %s", exist);
312 return;
313 }
314 }
315 fprintf (stderr, "cannot find %s\n", name);
316 }
317
318 /* IsExists - returns true if a file, Name, exists. It returns false
319 otherwise. */
320
321 static int
322 IsExists (char *Name)
323 {
324 struct stat buf;
325
326 return (stat (Name, &buf) == 0);
327 }
328
329 /* add_function - adds a name to the list of functions, in order. */
330
331 void
332 add_function (char *name)
333 {
334 functList *p = (functList *)malloc (sizeof (functList));
335 p->functname = (char *)malloc (strlen (name) + 1);
336 strcpy (p->functname, name);
337
338 if (head == NULL)
339 {
340 head = p;
341 tail = p;
342 p->next = NULL;
343 }
344 else
345 {
346 tail->next = p;
347 tail = p;
348 tail->next = NULL;
349 }
350 }
351
352 static void
353 GenerateInitCalls (functList *p)
354 {
355 while (p != NULL)
356 {
357 printf (" _M2_%s_init (argc, argv, envp);\n", p->functname);
358 p = p->next;
359 }
360 }
361
362 static void
363 GenerateFinishCalls (functList *p)
364 {
365 if (p->next != NULL)
366 GenerateFinishCalls (p->next);
367 printf (" _M2_%s_finish (argc, argv, envp);\n", p->functname);
368 }
369
370 static void
371 GeneratePrototypes (functList *p)
372 {
373 while (p != NULL)
374 {
375 if (langC)
376 {
377 printf ("extern void _M2_%s_init (int argc, char *argv[], char *envp[]);\n",
378 p->functname);
379 printf ("extern void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n",
380 p->functname);
381 }
382 else
383 {
384 printf ("extern \"C\" void _M2_%s_init (int argc, char *argv[], char *envp[]);\n",
385 p->functname);
386 printf ("extern \"C\" void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n",
387 p->functname);
388 }
389 p = p->next;
390 }
391 }
392
393 /* ParseFileStartup - generates the startup code. */
394
395 static void
396 ParseFileStartup (void)
397 {
398 char name[MAX_FILE_NAME];
399 functList *p;
400
401 while (PutChar (GetChar ()) != (char)EOF)
402 {
403 CopyUntilEolInto (name);
404 if ((strlen (name) > 0) && (strcmp (name, "mod_init") != 0)
405 && (name[0] != '#'))
406 add_function (name);
407 }
408 GeneratePrototypes (head);
409 printf ("extern");
410 if (!langC)
411 printf (" \"C\"");
412 printf (" void _exit(int);\n");
413
414 printf ("\n\nint %s(int argc, char *argv[], char *envp[])\n", NameOfMain);
415 printf ("{\n");
416 GenerateInitCalls (head);
417 GenerateFinishCalls (head);
418 if (ExitNeeded)
419 printf (" _exit(0);\n");
420 printf (" return(0);\n");
421 printf ("}\n");
422 }
423
424 /* OpenOutputFile - shut down stdout and open the new mod_init.c */
425
426 static void
427 OpenOutputFile (void)
428 {
429 if (strcmp (NameOfFile, "-") != 0)
430 {
431 if (close (STDOUT) != 0)
432 {
433 ERROR ("Unable to close stdout");
434 exit (1);
435 }
436 OutputFile = creat (NameOfFile, 0666);
437 if (OutputFile != STDOUT)
438 {
439 ERROR ("Expected that the file descriptor should be 1");
440 }
441 }
442 }
443
444 /* CloseFile - flush and close the file. */
445
446 static void
447 CloseFile (void)
448 {
449 #if 0
450 fflush(stdout);
451 if (close(STDOUT) != 0) {
452 ERROR("Unable to close our output file"); exit(1);
453 }
454 #endif
455 }
456
457 /* CopyUntilEof - copies from the current input marker until ENDOFILE
458 is reached. */
459
460 static void
461 CopyUntilEof (void)
462 {
463 char ch;
464
465 while ((ch = GetChar ()) != ENDOFILE)
466 putchar (ch);
467 }
468
469 /* CopyUntilEol - copies from the current input marker until '\n' is
470 reached. */
471
472 static void
473 CopyUntilEol (void)
474 {
475 char ch;
476
477 while (((ch = GetChar ()) != '\n') && (ch != (char)EOF))
478 putchar (ch);
479 if (ch == '\n')
480 putchar (ch);
481 }
482
483 /* CopyUntilEolInto - copies from the current input marker until '\n'
484 is reached into a Buffer. */
485
486 static void
487 CopyUntilEolInto (char *Buffer)
488 {
489 char ch;
490 int i = 0;
491
492 while (((ch = GetChar ()) != '\n') && (ch != (char)EOF))
493 {
494 Buffer[i] = ch;
495 i++;
496 }
497 if ((ch == '\n') || (ch == (char)EOF))
498 Buffer[i] = (char)0;
499 }
500
501 /* IsSym - returns true if string, s, was found in the input stream.
502 The input stream is uneffected. */
503
504 static int
505 IsSym (char *s)
506 {
507 int i = 0;
508
509 while ((s[i] != (char)0) && (s[i] == PutChar (GetChar ())))
510 {
511 GetChar ();
512 i++;
513 }
514 if (s[i] == (char)0)
515 {
516 PushBack (s);
517 /* found s in input string. */
518 return (TRUE);
519 }
520 else
521 {
522 /* push back the characters we have scanned. */
523 if (i > 0)
524 {
525 do
526 {
527 i--;
528 PutChar (s[i]);
529 }
530 while (i > 0);
531 }
532 return (FALSE);
533 }
534 }
535
536 /* SymIs - returns true if string, s, was found in the input stream.
537 The token s is consumed from the input stream. */
538
539 static int
540 SymIs (char *s)
541 {
542 int i = 0;
543
544 while ((s[i] != (char)0) && (s[i] == PutChar (GetChar ())))
545 {
546 GetChar ();
547 i++;
548 }
549 if (s[i] == (char)0)
550 {
551 /* found s in input string. */
552 return (TRUE);
553 }
554 else
555 {
556 /* push back the characters we have scanned. */
557 if (i > 0)
558 {
559 do
560 {
561 i--;
562 PutChar (s[i]);
563 }
564 while (i > 0);
565 }
566 return (FALSE);
567 }
568 }
569
570 /* FindString - keeps on reading input until a string, String, is
571 matched. If end of file is reached then FALSE is returned, otherwise
572 TRUE is returned. */
573
574 static int
575 FindString (char *String)
576 {
577 int StringIndex = 0;
578 int Found = FALSE;
579 int eof = FALSE;
580 char ch;
581
582 while ((!Found) && (!eof))
583 {
584 if (String[StringIndex] == (char)0)
585 /* must have found string. */
586 Found = TRUE;
587 else
588 {
589 ch = GetChar ();
590 eof = (ch == ENDOFILE);
591 if (ch == String[StringIndex])
592 StringIndex++;
593 else
594 StringIndex = 0;
595 }
596 }
597 return (Found);
598 }
599
600 /* GetNL - keeps on reading input from until a new line is found. */
601
602 static void
603 GetNL (void)
604 {
605 char ch;
606
607 while ((ch = GetChar ()) != '\n')
608 putchar (ch);
609 putchar ('\n');
610 }
611
612 /* GetChar - returns the current character in input. */
613
614 static char
615 GetChar (void)
616 {
617 char ch;
618
619 if (StackPtr > 0)
620 {
621 StackPtr--;
622 return (Stack[StackPtr]);
623 }
624 else
625 {
626 if (GetSingleChar (&ch))
627 return (ch);
628 else
629 return (ENDOFILE);
630 }
631 }
632
633 #define MAXBUF 0x1000
634 static int Pointer = 0;
635 static int AmountRead = 0;
636 static char Buffer[MAXBUF];
637
638 /* ResetBuffer - resets the buffer information to an initial state. */
639
640 static void
641 ResetBuffer (void)
642 {
643 StackPtr = 0;
644 Pointer = 0;
645 AmountRead = 0;
646 }
647
648 /* GetSingleChar - gets a single character from input. TRUE is
649 returned upon success. */
650
651 static int
652 GetSingleChar (char *ch)
653 {
654 if (Pointer == AmountRead)
655 {
656 AmountRead = read (CurrentFile, &Buffer, MAXBUF);
657 if (AmountRead < 0)
658 AmountRead = 0;
659 Pointer = 0;
660 }
661 if (Pointer == AmountRead)
662 {
663 *ch = ENDOFILE;
664 return (FALSE);
665 }
666 else
667 {
668 *ch = Buffer[Pointer];
669 Pointer++;
670 return (TRUE);
671 }
672 }
673
674 /* InRange - returns true if Element is within the range Min..Max. */
675
676 static int
677 InRange (int Element, unsigned int Min, unsigned int Max)
678 {
679 return ((Element >= Min) && (Element <= Max));
680 }
681
682 /* PutChar - pushes a character back onto input. This character is
683 also returned. */
684
685 static char
686 PutChar (char ch)
687 {
688 if (StackPtr < MAXSTACK)
689 {
690 Stack[StackPtr] = ch;
691 StackPtr++;
692 }
693 else
694 {
695 ERROR ("Stack overflow in PutChar");
696 }
697 return (ch);
698 }
699
700 /* IsSpace - returns true if character, ch, is a space. */
701
702 static int
703 IsSpace (char ch)
704 {
705 return ((ch == ' ') || (ch == '\t'));
706 }
707
708 /* SkipSpaces - eats up spaces in input. */
709
710 static void
711 SkipSpaces (void)
712 {
713 while (IsSpace (PutChar (GetChar ())))
714 putchar (GetChar ());
715 }
716
717 /* SilentSkipSpaces - eats up spaces in input. */
718
719 static void
720 SilentSkipSpaces (void)
721 {
722 char ch;
723
724 while (IsSpace (PutChar (GetChar ())))
725 ch = GetChar (); /* throw away character. */
726 }
727
728 /* SkipText - skips ascii text, it does not skip white spaces. */
729
730 static void
731 SkipText (void)
732 {
733 while (!IsSpace (PutChar (GetChar ())))
734 putchar (GetChar ());
735 }
736
737 /* SilentSkipText - skips ascii text, it does not skip white spaces. */
738
739 static void
740 SilentSkipText (void)
741 {
742 char ch;
743
744 while (!IsSpace (PutChar (GetChar ())))
745 ch = GetChar (); /* throw away character. */
746 }
747
748 /* PushBack - pushes a string, backwards onto the input stack. */
749
750 static void
751 PushBack (char *s)
752 {
753 int i;
754
755 i = strlen (s);
756 while (i > 0)
757 {
758 i--;
759 PutChar (s[i]);
760 }
761 }
762
763 /* IsDigit - returns true if a character, ch, is a decimal digit. */
764
765 static int
766 IsDigit (char ch)
767 {
768 return (((ch >= '0') && (ch <= '9')));
769 }
770
771 /* GetName - returns the next name found. */
772
773 static void
774 GetName (char *Name)
775 {
776 int i;
777 char ch;
778
779 SkipSpaces ();
780 ch = GetChar ();
781 i = 0;
782 while (!IsSpace (ch))
783 {
784 Name[i] = ch;
785 i++;
786 ch = GetChar ();
787 }
788 Name[i] = '\0';
789 }
790
791 /* FindSource - open source file on StdIn. */
792
793 static void
794 FindSource (char *Name)
795 {
796 if (close (STDIN) != 0)
797 {
798 ERROR ("close on STDIN failed");
799 }
800 CurrentFile = open (Name, O_RDONLY);
801 if (CurrentFile < 0)
802 {
803 perror ("failed to open file");
804 exit (1);
805 }
806 if (CurrentFile != STDIN)
807 {
808 ERROR ("Expecting file descriptor value of 1");
809 }
810 }
This page took 0.07116 seconds and 5 git commands to generate.