]>
gcc.gnu.org Git - gcc.git/blob - gcc/m2/tools-src/mklink.c
1 /* mklink.c creates startup code and the link command line.
3 Copyright (C) 2000-2022 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
6 This file is part of GNU Modula-2.
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)
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.
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/>. */
26 #define MAX_FILE_NAME 8192
30 #define ENDOFILE ((char)-1)
32 (fprintf (stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) \
35 ((Debug) && (fprintf (stderr, "%s\n", X) && (fflush (stderr))))
42 #define FALSE (1 == 0)
45 typedef struct functlist
48 struct functlist
*next
;
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
);
83 /* Global variables. */
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. */
101 /* addLibrary - adds libname to the list of libraries to be linked. */
104 addLibrary (char *libname
)
106 if (libraries
== NULL
)
107 libraries
= strdup (libname
);
110 char *old
= libraries
;
112 = (char *)malloc (strlen (libname
) + strlen (libraries
) + 1 + 1);
113 strcpy (newlib
, libraries
);
114 strcat (newlib
, " ");
115 strcat (newlib
, libname
);
121 /* addGccArg - adds arg to the list of gcc arguments. */
124 addGccArg (char *arg
)
131 char *newarg
= (char *)malloc (strlen (old
) + strlen (arg
) + 1 + 1);
132 strcpy (newarg
, old
);
133 strcat (newarg
, " ");
134 strcat (newarg
, arg
);
141 main (int argc
, char *argv
[])
147 if (strcmp (argv
[1], "-l") == 0)
148 LinkCommandLine
= TRUE
;
149 else if (strcmp (argv
[1], "-s") == 0)
150 LinkCommandLine
= FALSE
;
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");
159 ProfilePCommand
= FALSE
;
160 ProfilePGCommand
= FALSE
;
164 if (strcmp (argv
[i
], "--langc++") == 0)
166 else if (strcmp (argv
[i
], "--langc") == 0)
168 else if (strncmp (argv
[i
], "-f", 2) == 0)
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)
176 else if (strcmp (argv
[i
], "--lib") == 0)
179 addLibrary (argv
[i
]);
181 else if (strcmp (argv
[i
], "--main") == 0)
184 NameOfMain
= argv
[i
];
186 else if (strcmp (argv
[i
], "--name") == 0)
189 NameOfFile
= argv
[i
];
197 fprintf (stderr
, "Usage: mklink (-l|-s) [--gcc|--g++] [--pg|-p] [--lib "
198 "library] [--main name] [--exit] --name filename "
199 "<modulelistfile>\n");
202 if (NameOfFile
== NULL
)
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");
213 /* ParseFile - parses the input file and generates the output file. */
216 ParseFile (char *Name
)
221 ParseFileLinkCommand ();
227 /* ParseFileLinkCommand - generates the link command. */
230 ParseFileLinkCommand (void)
232 char name
[MAX_FILE_NAME
];
246 printf ("%s -g ", s
);
249 printf ("%s ", args
);
251 l
= getenv ("LDFLAGS");
255 c
= getenv ("CFLAGS");
259 if (ProfilePGCommand
)
261 else if (ProfilePCommand
)
264 while (PutChar (GetChar ()) != (char)EOF
)
266 CopyUntilEolInto (name
);
268 name
[10] = (char)0; /* truncate object file name. */
270 if ((strlen (name
) > 0) && (name
[0] != '#'))
273 printf (" %s\n", libraries
);
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. */
281 FindObject (char *Name
)
289 if (getenv ("M2PATH") == NULL
)
290 strcpy (m2path
, ".");
292 strcpy (m2path
, getenv ("M2PATH"));
294 snprintf (name
, sizeof (name
), "%s.o", Name
);
296 while (m2path
[p
] != (char)0)
299 while ((m2path
[p
] != (char)0) && (m2path
[p
] != ' '))
301 m2search
[s
] = m2path
[p
];
305 if (m2path
[p
] == ' ')
307 m2search
[s
] = (char)0;
308 snprintf (exist
, sizeof (exist
), "%s/%s", m2search
, name
);
309 if (IsExists (exist
))
311 printf (" %s", exist
);
315 fprintf (stderr
, "cannot find %s\n", name
);
318 /* IsExists - returns true if a file, Name, exists. It returns false
322 IsExists (char *Name
)
326 return (stat (Name
, &buf
) == 0);
329 /* add_function - adds a name to the list of functions, in order. */
332 add_function (char *name
)
334 functList
*p
= (functList
*)malloc (sizeof (functList
));
335 p
->functname
= (char *)malloc (strlen (name
) + 1);
336 strcpy (p
->functname
, name
);
353 GenerateInitCalls (functList
*p
)
357 printf (" _M2_%s_init (argc, argv, envp);\n", p
->functname
);
363 GenerateFinishCalls (functList
*p
)
366 GenerateFinishCalls (p
->next
);
367 printf (" _M2_%s_finish (argc, argv, envp);\n", p
->functname
);
371 GeneratePrototypes (functList
*p
)
377 printf ("extern void _M2_%s_init (int argc, char *argv[], char *envp[]);\n",
379 printf ("extern void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n",
384 printf ("extern \"C\" void _M2_%s_init (int argc, char *argv[], char *envp[]);\n",
386 printf ("extern \"C\" void _M2_%s_finish (int argc, char *argv[], char *envp[]);\n",
393 /* ParseFileStartup - generates the startup code. */
396 ParseFileStartup (void)
398 char name
[MAX_FILE_NAME
];
401 while (PutChar (GetChar ()) != (char)EOF
)
403 CopyUntilEolInto (name
);
404 if ((strlen (name
) > 0) && (strcmp (name
, "mod_init") != 0)
408 GeneratePrototypes (head
);
412 printf (" void _exit(int);\n");
414 printf ("\n\nint %s(int argc, char *argv[], char *envp[])\n", NameOfMain
);
416 GenerateInitCalls (head
);
417 GenerateFinishCalls (head
);
419 printf (" _exit(0);\n");
420 printf (" return(0);\n");
424 /* OpenOutputFile - shut down stdout and open the new mod_init.c */
427 OpenOutputFile (void)
429 if (strcmp (NameOfFile
, "-") != 0)
431 if (close (STDOUT
) != 0)
433 ERROR ("Unable to close stdout");
436 OutputFile
= creat (NameOfFile
, 0666);
437 if (OutputFile
!= STDOUT
)
439 ERROR ("Expected that the file descriptor should be 1");
444 /* CloseFile - flush and close the file. */
451 if (close(STDOUT
) != 0) {
452 ERROR("Unable to close our output file"); exit(1);
457 /* CopyUntilEof - copies from the current input marker until ENDOFILE
465 while ((ch
= GetChar ()) != ENDOFILE
)
469 /* CopyUntilEol - copies from the current input marker until '\n' is
477 while (((ch
= GetChar ()) != '\n') && (ch
!= (char)EOF
))
483 /* CopyUntilEolInto - copies from the current input marker until '\n'
484 is reached into a Buffer. */
487 CopyUntilEolInto (char *Buffer
)
492 while (((ch
= GetChar ()) != '\n') && (ch
!= (char)EOF
))
497 if ((ch
== '\n') || (ch
== (char)EOF
))
501 /* IsSym - returns true if string, s, was found in the input stream.
502 The input stream is uneffected. */
509 while ((s
[i
] != (char)0) && (s
[i
] == PutChar (GetChar ())))
517 /* found s in input string. */
522 /* push back the characters we have scanned. */
536 /* SymIs - returns true if string, s, was found in the input stream.
537 The token s is consumed from the input stream. */
544 while ((s
[i
] != (char)0) && (s
[i
] == PutChar (GetChar ())))
551 /* found s in input string. */
556 /* push back the characters we have scanned. */
570 /* FindString - keeps on reading input until a string, String, is
571 matched. If end of file is reached then FALSE is returned, otherwise
575 FindString (char *String
)
582 while ((!Found
) && (!eof
))
584 if (String
[StringIndex
] == (char)0)
585 /* must have found string. */
590 eof
= (ch
== ENDOFILE
);
591 if (ch
== String
[StringIndex
])
600 /* GetNL - keeps on reading input from until a new line is found. */
607 while ((ch
= GetChar ()) != '\n')
612 /* GetChar - returns the current character in input. */
622 return (Stack
[StackPtr
]);
626 if (GetSingleChar (&ch
))
633 #define MAXBUF 0x1000
634 static int Pointer
= 0;
635 static int AmountRead
= 0;
636 static char Buffer
[MAXBUF
];
638 /* ResetBuffer - resets the buffer information to an initial state. */
648 /* GetSingleChar - gets a single character from input. TRUE is
649 returned upon success. */
652 GetSingleChar (char *ch
)
654 if (Pointer
== AmountRead
)
656 AmountRead
= read (CurrentFile
, &Buffer
, MAXBUF
);
661 if (Pointer
== AmountRead
)
668 *ch
= Buffer
[Pointer
];
674 /* InRange - returns true if Element is within the range Min..Max. */
677 InRange (int Element
, unsigned int Min
, unsigned int Max
)
679 return ((Element
>= Min
) && (Element
<= Max
));
682 /* PutChar - pushes a character back onto input. This character is
688 if (StackPtr
< MAXSTACK
)
690 Stack
[StackPtr
] = ch
;
695 ERROR ("Stack overflow in PutChar");
700 /* IsSpace - returns true if character, ch, is a space. */
705 return ((ch
== ' ') || (ch
== '\t'));
708 /* SkipSpaces - eats up spaces in input. */
713 while (IsSpace (PutChar (GetChar ())))
714 putchar (GetChar ());
717 /* SilentSkipSpaces - eats up spaces in input. */
720 SilentSkipSpaces (void)
724 while (IsSpace (PutChar (GetChar ())))
725 ch
= GetChar (); /* throw away character. */
728 /* SkipText - skips ascii text, it does not skip white spaces. */
733 while (!IsSpace (PutChar (GetChar ())))
734 putchar (GetChar ());
737 /* SilentSkipText - skips ascii text, it does not skip white spaces. */
740 SilentSkipText (void)
744 while (!IsSpace (PutChar (GetChar ())))
745 ch
= GetChar (); /* throw away character. */
748 /* PushBack - pushes a string, backwards onto the input stack. */
763 /* IsDigit - returns true if a character, ch, is a decimal digit. */
768 return (((ch
>= '0') && (ch
<= '9')));
771 /* GetName - returns the next name found. */
782 while (!IsSpace (ch
))
791 /* FindSource - open source file on StdIn. */
794 FindSource (char *Name
)
796 if (close (STDIN
) != 0)
798 ERROR ("close on STDIN failed");
800 CurrentFile
= open (Name
, O_RDONLY
);
803 perror ("failed to open file");
806 if (CurrentFile
!= STDIN
)
808 ERROR ("Expecting file descriptor value of 1");
This page took 0.07116 seconds and 5 git commands to generate.