1 (* keyc maintains the C name scope and avoids C/C++ name conflicts.
2 Copyright (C) 2016-2024 Free Software Foundation, Inc.
4 This file is part of GNU Modula-2.
6 GNU Modula-2 is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. *)
20 IMPLEMENTATION MODULE keyc
;
22 FROM mcPretty
IMPORT pretty
, print
, prints
, setNeedSpace
, noSpace
;
23 FROM Storage
IMPORT ALLOCATE
;
24 FROM DynamicStrings
IMPORT InitString
, KillString
, ConCat
, ConCatChar
,
25 Mark
, string
, InitStringCharStar
;
26 FROM symbolKey
IMPORT symbolTree
, getSymKey
, putSymKey
, initTree
, killTree
;
27 FROM nameKey
IMPORT makeKey
, makekey
, keyToCharStar
;
28 FROM mcOptions
IMPORT getHPrefix
, getGccConfigSystem
, useBool
;
32 scope
= POINTER TO RECORD
87 checkGccConfigSystem - issues the GCC include config.h, include system.h
88 instead of the standard host include.
91 PROCEDURE checkGccConfigSystem (p
: pretty
) ;
93 IF getGccConfigSystem ()
97 initializedGCC
:= TRUE ;
98 print (p
, '#include "config.h"\n');
99 print (p
, '#include "system.h"\n');
103 END checkGccConfigSystem
;
107 useGccTree - indicate we have imported tree from gcctypes.
110 PROCEDURE useGccTree
;
117 useGccLocation - indicate we have imported tree from gcctypes.
120 PROCEDURE useGccLocation
;
122 seenGccLocation
:= TRUE
127 useStorage - indicate we have used storage.
130 PROCEDURE useStorage
;
137 useFree - indicate we have used free.
147 useMalloc - indicate we have used malloc.
150 PROCEDURE useMalloc
;
157 useProc - indicate we have used proc.
167 useTrue - indicate we have used TRUE.
177 useFalse - indicate we have used FALSE.
187 useNull - indicate we have used NULL.
197 useMemcpy - indicate we have used memcpy.
200 PROCEDURE useMemcpy
;
207 useIntMin - indicate we have used INT_MIN.
210 PROCEDURE useIntMin
;
217 useUIntMin - indicate we have used UINT_MIN.
220 PROCEDURE useUIntMin
;
227 useLongMin - indicate we have used LONG_MIN.
230 PROCEDURE useLongMin
;
237 useULongMin - indicate we have used ULONG_MIN.
240 PROCEDURE useULongMin
;
247 useCharMin - indicate we have used CHAR_MIN.
250 PROCEDURE useCharMin
;
257 useUCharMin - indicate we have used UCHAR_MIN.
260 PROCEDURE useUCharMin
;
267 useUIntMin - indicate we have used UINT_MIN.
270 PROCEDURE useUIntMin
;
277 useIntMax - indicate we have used INT_MAX.
280 PROCEDURE useIntMax
;
287 useUIntMax - indicate we have used UINT_MAX.
290 PROCEDURE useUIntMax
;
297 useLongMax - indicate we have used LONG_MAX.
300 PROCEDURE useLongMax
;
307 useULongMax - indicate we have used ULONG_MAX.
310 PROCEDURE useULongMax
;
317 useCharMax - indicate we have used CHAR_MAX.
320 PROCEDURE useCharMax
;
327 useUCharMax - indicate we have used UChar_MAX.
330 PROCEDURE useUCharMax
;
337 useUIntMax - indicate we have used UINT_MAX.
340 PROCEDURE useUIntMax
;
347 useSize_t - indicate we have used size_t.
350 PROCEDURE useSize_t
;
357 useSSize_t - indicate we have used ssize_t.
360 PROCEDURE useSSize_t
;
362 seenSSize_t
:= TRUE ;
368 useLabs - indicate we have used labs.
378 useAbs - indicate we have used abs.
388 useFabs - indicate we have used fabs.
398 useFabsl - indicate we have used fabsl.
408 useM2RTS - indicate we have used M2RTS in the converted code.
418 useStrlen - indicate we have used strlen in the converted code.
421 PROCEDURE useStrlen
;
428 useCtype - indicate we have used the toupper function.
438 checkGccTypes - if we have imported tree or location_t from gcctypes
439 then we include the gcc headers.
442 PROCEDURE checkGccTypes (p
: pretty
) ;
444 IF seenGccTree
OR seenGccLocation
446 print (p
, '#include "gcc-consolidation.h"\n\n')
455 PROCEDURE checkCtype (p
: pretty
) ;
459 checkGccConfigSystem (p
) ;
460 IF getGccConfigSystem ()
462 (* GCC header files use a safe variant. *)
463 print (p
, "#include <safe-ctype.h>\n")
465 print (p
, "#include <ctype.h>\n")
472 checkAbs - check to see if the abs family, size_t or ssize_t have been used.
475 PROCEDURE checkAbs (p
: pretty
) ;
477 IF seenLabs
OR seenAbs
OR seenFabs
OR seenFabsl
OR seenSize_t
OR seenSSize_t
479 checkGccConfigSystem (p
);
480 IF NOT getGccConfigSystem ()
482 print (p
, "#include <stdlib.h>\n")
492 PROCEDURE checkLimits (p
: pretty
) ;
494 IF seenMemcpy
OR seenIntMin
OR seenUIntMin
OR
495 seenLongMin
OR seenULongMin
OR seenCharMin
OR
496 seenUCharMin
OR (* seenUIntMin OR *) seenIntMax
OR
497 seenUIntMax
OR seenLongMax
OR seenULongMax
OR
498 seenCharMax
OR seenUCharMax (* OR seenUIntMax *)
500 checkGccConfigSystem (p
);
501 IF NOT getGccConfigSystem ()
503 print (p
, "#include <limits.h>\n")
513 PROCEDURE checkFreeMalloc (p
: pretty
) ;
515 IF seenFree
OR seenMalloc
517 checkGccConfigSystem (p
);
518 IF NOT getGccConfigSystem ()
520 print (p
, "#include <stdlib.h>\n")
523 END checkFreeMalloc
;
530 PROCEDURE checkStorage (p
: pretty
) ;
534 print (p
, '# include "') ;
535 prints (p
, getHPrefix ()) ;
536 print (p
, 'Storage.h"\n')
545 PROCEDURE checkProc (p
: pretty
) ;
549 print (p
, "# if !defined (PROC_D)\n") ;
550 print (p
, "# define PROC_D\n") ;
551 print (p
, " typedef void (*PROC_t) (void);\n") ;
552 print (p
, " typedef struct { PROC_t proc; } PROC;\n") ;
553 print (p
, "# endif\n\n")
562 PROCEDURE checkTrue (p
: pretty
) ;
566 print (p
, "# if !defined (TRUE)\n") ;
567 print (p
, "# define TRUE (1==1)\n") ;
568 print (p
, "# endif\n\n")
577 PROCEDURE checkFalse (p
: pretty
) ;
581 print (p
, "# if !defined (FALSE)\n") ;
582 print (p
, "# define FALSE (1==0)\n") ;
583 print (p
, "# endif\n\n")
592 PROCEDURE checkNull (p
: pretty
) ;
596 checkGccConfigSystem (p
);
597 IF NOT getGccConfigSystem ()
599 print (p
, "#include <stddef.h>\n")
609 PROCEDURE checkMemcpy (p
: pretty
) ;
611 IF seenMemcpy
OR seenStrlen
613 checkGccConfigSystem (p
);
614 IF NOT getGccConfigSystem ()
616 print (p
, "#include <string.h>\n")
626 PROCEDURE checkM2RTS (p
: pretty
) ;
630 print (p
, '# include "') ;
631 prints (p
, getHPrefix ()) ;
632 print (p
, 'M2RTS.h"\n')
638 useException - use the exceptions module, mcrts.
641 PROCEDURE useException
;
643 seenException
:= TRUE
648 checkException - check to see if exceptions were used.
651 PROCEDURE checkException (p
: pretty
) ;
655 print (p
, '# include "Gmcrts.h"\n')
661 useThrow - use the throw function.
671 checkThrow - check to see if the throw function is used.
674 PROCEDURE checkThrow (p
: pretty
) ;
678 (* print (p, '# include "sys/cdefs.h"\n') ; *)
679 print (p
, '#ifndef __cplusplus\n') ;
680 print (p
, 'extern void throw (unsigned int);\n') ;
681 print (p
, '#endif\n')
687 useUnistd - need to use unistd.h call using open/close/read/write require this header.
690 PROCEDURE useUnistd
;
697 checkUnistd - check to see if the unistd.h header file is required.
700 PROCEDURE checkUnistd (p
: pretty
) ;
704 checkGccConfigSystem (p
);
705 IF NOT getGccConfigSystem ()
707 print (p
, '#include <unistd.h>\n')
714 useComplex - use the complex data type.
717 PROCEDURE useComplex
;
724 checkComplex - check to see if the type complex was used.
727 PROCEDURE checkComplex (p
: pretty
) ;
731 checkGccConfigSystem (p
);
732 IF NOT getGccConfigSystem ()
734 print (p
, '# include <complex.h>\n')
741 checkSysTypes - emit header for sys/types.h if necessary.
744 PROCEDURE checkSysTypes (p
: pretty
) ;
748 checkGccConfigSystem (p
);
749 IF NOT getGccConfigSystem ()
751 print (p
, '# include <sys/types.h>\n')
758 fixNullPointerConst - fixup for NULL on some C++11 systems.
761 PROCEDURE fixNullPointerConst (p
: pretty
) ;
765 print (p
, '#if defined(__cplusplus)\n') ;
766 print (p
, '# undef NULL\n') ;
767 print (p
, '# define NULL 0\n') ;
768 print (p
, '#endif\n')
770 END fixNullPointerConst
;
777 PROCEDURE genBool (p
: pretty
) ;
781 print (p
, '#include <stdbool.h>\n') ;
787 genDefs - generate definitions or includes for all
788 macros and prototypes used.
791 PROCEDURE genDefs (p
: pretty
) ;
794 checkFreeMalloc (p
) ;
810 fixNullPointerConst (p
)
815 genConfigSystem - generate include files for config.h and system.h
816 within the GCC framework.
819 PROCEDURE genConfigSystem (p
: pretty
) ;
821 checkGccConfigSystem (p
)
822 END genConfigSystem
;
829 PROCEDURE new (n
: node
) : scope
;
838 freeList
:= freeList^.next
845 enterScope - enter a scope defined by, n.
848 PROCEDURE enterScope (n
: node
) ;
855 symbols
:= initTree () ;
863 leaveScope - leave the scope defined by, n.
866 PROCEDURE leaveScope (n
: node
) ;
873 stack
:= stack^.next
;
886 mangle1 - returns TRUE if name is unique if we add _
890 PROCEDURE mangle1 (n
: Name
; VAR m
: String
; scopes
: BOOLEAN) : BOOLEAN ;
892 m
:= KillString (m
) ;
893 m
:= InitStringCharStar (keyToCharStar (n
)) ;
894 m
:= ConCatChar (m
, '_') ;
895 RETURN NOT clash (makekey (string (m
)), scopes
)
900 mangle2 - returns TRUE if name is unique if we prepend _
904 PROCEDURE mangle2 (n
: Name
; VAR m
: String
; scopes
: BOOLEAN) : BOOLEAN ;
906 m
:= KillString (m
) ;
907 m
:= InitStringCharStar (keyToCharStar (n
)) ;
908 m
:= ConCat (InitString ('_'), Mark (m
)) ;
909 RETURN NOT clash (makekey (string (m
)), scopes
)
914 mangleN - keep adding '_' to the end of n until it
918 PROCEDURE mangleN (n
: Name
; VAR m
: String
; scopes
: BOOLEAN) : BOOLEAN ;
920 m
:= KillString (m
) ;
921 m
:= InitStringCharStar (keyToCharStar (n
)) ;
923 m
:= ConCatChar (m
, '_') ;
924 IF NOT clash (makekey (string (m
)), scopes
)
933 clash - returns TRUE if there is a clash with name, n,
934 in the current scope or C keywords or C macros.
937 PROCEDURE clash (n
: Name
; scopes
: BOOLEAN) : BOOLEAN ;
939 IF (getSymKey (macros
, n
) #
NIL) OR
940 (getSymKey (keywords
, n
) #
NIL)
944 RETURN scopes
AND (getSymKey (stack^.symbols
, n
) #
NIL)
949 cname - attempts to declare a symbol with name, n, in the
950 current scope. If there is no conflict with the
951 target language then NIL is returned, otherwise
952 a mangled name is returned as a String.
953 If scopes is FALSE then only the keywords and
954 macros are detected for a clash (all scoping
958 PROCEDURE cname (n
: Name
; scopes
: BOOLEAN) : String
;
965 IF mangle1 (n
, m
, scopes
) OR mangle2 (n
, m
, scopes
) OR mangleN (n
, m
, scopes
)
969 (* no longer a clash with, m, so add it to the current scope. *)
970 n
:= makekey (string (m
)) ;
971 putSymKey (stack^.symbols
, n
, m
)
974 (* mangleN must always succeed. *)
979 (* no clash, add it to the current scope. *)
980 putSymKey (stack^.symbols
, n
, InitStringCharStar (keyToCharStar (n
)))
987 cnamen - attempts to declare a symbol with name, n, in the
988 current scope. If there is no conflict with the
989 target language then NIL is returned, otherwise
990 a mangled name is returned as a Name
991 If scopes is FALSE then only the keywords and
992 macros are detected for a clash (all scoping
996 PROCEDURE cnamen (n
: Name
; scopes
: BOOLEAN) : Name
;
1001 IF clash (n
, scopes
)
1003 IF mangle1 (n
, m
, scopes
) OR mangle2 (n
, m
, scopes
) OR mangleN (n
, m
, scopes
)
1005 n
:= makekey (string (m
)) ;
1008 (* no longer a clash with, m, so add it to the current scope. *)
1009 putSymKey (stack^.symbols
, n
, m
)
1012 (* mangleN must always succeed. *)
1017 (* no clash, add it to the current scope. *)
1018 putSymKey (stack^.symbols
, n
, InitStringCharStar (keyToCharStar (n
)))
1020 m
:= KillString (m
) ;
1026 cp - include C++ keywords and standard declarations to avoid.
1031 IF NOT initializedCP
1033 initializedCP
:= TRUE ;
1040 initCP - add the extra keywords and standard definitions used by C++.
1045 add (keywords
, 'delete') ;
1046 add (keywords
, 'try') ;
1047 add (keywords
, 'catch') ;
1048 add (keywords
, 'operator') ;
1049 add (keywords
, 'complex') ;
1050 add (keywords
, 'export') ;
1051 add (keywords
, 'public')
1059 PROCEDURE add (s
: symbolTree
; a
: ARRAY OF CHAR) ;
1061 putSymKey (s
, makeKey (a
), InitString (a
))
1066 initMacros - macros and library function names to avoid.
1069 PROCEDURE initMacros
;
1071 macros
:= initTree () ;
1072 add (macros
, 'FILE') ;
1073 add (macros
, 'EOF') ;
1074 add (macros
, 'stdio') ;
1075 add (macros
, 'stdout') ;
1076 add (macros
, 'stderr') ;
1077 add (macros
, 'write') ;
1078 add (macros
, 'read') ;
1079 add (macros
, 'exit') ;
1080 add (macros
, 'abs') ;
1081 add (macros
, 'optarg') ;
1082 add (macros
, 'div') ;
1083 add (macros
, 'sin') ;
1084 add (macros
, 'cos') ;
1085 add (macros
, 'tan') ;
1086 add (macros
, 'log10') ;
1087 add (macros
, 'trunc') ;
1089 add (macros
, 'csqrt') ;
1090 add (macros
, 'strlen') ;
1091 add (macros
, 'strcpy') ;
1092 add (macros
, 'free') ;
1093 add (macros
, 'malloc') ;
1094 add (macros
, 'time') ;
1095 add (macros
, 'main') ;
1096 add (macros
, 'true') ;
1097 add (macros
, 'false') ;
1098 add (macros
, 'sigfpe')
1103 initKeywords - keywords to avoid.
1106 PROCEDURE initKeywords
;
1108 keywords
:= initTree () ;
1109 add (keywords
, 'auto') ;
1110 add (keywords
, 'break') ;
1111 add (keywords
, 'case') ;
1112 add (keywords
, 'char') ;
1113 add (keywords
, 'const') ;
1114 add (keywords
, 'continue') ;
1115 add (keywords
, 'default') ;
1116 add (keywords
, 'do') ;
1117 add (keywords
, 'double') ;
1118 add (keywords
, 'else') ;
1119 add (keywords
, 'enum') ;
1120 add (keywords
, 'extern') ;
1121 add (keywords
, 'float') ;
1122 add (keywords
, 'for') ;
1123 add (keywords
, 'goto') ;
1124 add (keywords
, 'if') ;
1125 add (keywords
, 'int') ;
1126 add (keywords
, 'long') ;
1127 add (keywords
, 'register') ;
1128 add (keywords
, 'return') ;
1129 add (keywords
, 'short') ;
1130 add (keywords
, 'signed') ;
1131 add (keywords
, 'sizeof') ;
1132 add (keywords
, 'static') ;
1133 add (keywords
, 'struct') ;
1134 add (keywords
, 'switch') ;
1135 add (keywords
, 'typedef') ;
1136 add (keywords
, 'union') ;
1137 add (keywords
, 'unsigned') ;
1138 add (keywords
, 'void') ;
1139 add (keywords
, 'volatile') ;
1140 add (keywords
, 'while') ;
1141 add (keywords
, 'and') ;
1142 add (keywords
, 'or') ;
1143 add (keywords
, 'not') ;
1144 add (keywords
, 'throw') ;
1145 add (keywords
, 'new')
1155 seenUnistd
:= FALSE ;
1156 seenThrow
:= FALSE ;
1158 seenMalloc
:= FALSE ;
1159 seenStorage
:= FALSE ;
1162 seenFalse
:= FALSE ;
1164 seenMemcpy
:= FALSE ;
1165 seenIntMin
:= FALSE ;
1166 seenUIntMin
:= FALSE ;
1167 seenLongMin
:= FALSE ;
1168 seenULongMin
:= FALSE ;
1169 seenCharMin
:= FALSE ;
1170 seenUCharMin
:= FALSE ;
1171 seenIntMax
:= FALSE ;
1172 seenUIntMax
:= FALSE ;
1173 seenLongMax
:= FALSE ;
1174 seenULongMax
:= FALSE ;
1175 seenCharMax
:= FALSE ;
1176 seenUCharMax
:= FALSE ;
1180 seenFabsl
:= FALSE ;
1181 seenException
:= FALSE ;
1182 seenComplex
:= FALSE ;
1183 seenM2RTS
:= FALSE ;
1184 seenStrlen
:= FALSE ;
1185 seenCtype
:= FALSE ;
1186 seenSize_t
:= FALSE ;
1187 seenSSize_t
:= FALSE ;
1188 seenSysTypes
:= FALSE ;
1189 seenGccTree
:= FALSE ;
1190 seenGccLocation
:= FALSE ;
1191 initializedCP
:= FALSE ;
1192 initializedGCC
:= FALSE ;