blob: 430e7ae52b1e986fcef26fb375844a1e1352d7d5 [file] [log] [blame]
/* "p2c", a Pascal to C translator.
Copyright (C) 1989, 1990, 1991 Free Software Foundation.
Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation (any version).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define define_globals
#define PROTO_TRANS_C
#include "trans.h"
#include <time.h>
/* Roadmap:
trans.h Declarations for all public global variables, types,
and macros. Functions are declared in separate
files p2c.{proto,hdrs} which are created
mechanically by the makeproto program.
trans.c Main program. Parses the p2crc file. Also reserves
storage for public globals in trans.h.
stuff.c Miscellaneous support routines.
out.c Routines to handle the writing of C code to the output
file. This includes line breaking and indentation
support.
comment.c Routines for managing comments and comment lists.
lex.c Lexical analyzer. Manages input files and streams,
splits input stream into Pascal tokens. Parses
compiler directives and special comments. Also keeps
the symbol table.
parse.c Parsing and writing statements and blocks.
decl.c Parsing and writing declarations.
expr.c Manipulating expressions.
pexpr.c Parsing and writing expressions.
funcs.c Built-in special functions and procedures.
dir.c Interface file to "external" functions and procedures
such as hpmods and citmods.
hpmods.c Definitions for HP-supplied Pascal modules.
citmods.c Definitions for some Caltech-local Pascal modules.
(Outside of Caltech this file is mostly useful
as a large body of examples of how to write your
own translator extensions.)
p2crc Control file (read when p2c starts up).
p2c.h Header file used by translated programs.
p2clib.c Run-time library used by translated programs.
*/
Static Strlist *tweaksymbols, *synonyms;
Strlist *addmacros;
Static void initrc()
{
int i;
for (i = 0; i < numparams; i++) {
switch (rctable[i].kind) {
case 'S':
case 'B':
*((short *)rctable[i].ptr) = rctable[i].def;
break;
case 'I':
case 'D':
*((int *)rctable[i].ptr) = rctable[i].def;
break;
case 'L':
*((long *)rctable[i].ptr) = rctable[i].def;
break;
case 'R':
*((double *)rctable[i].ptr) = rctable[i].def/100.0;
break;
case 'U':
case 'C':
*((char *)rctable[i].ptr) = 0;
break;
case 'A':
*((Strlist **)rctable[i].ptr) = NULL;
break;
case 'X':
if (rctable[i].def == 1)
*((Strlist **)rctable[i].ptr) = NULL;
break;
}
rcprevvalues[i] = NULL;
}
tweaksymbols = NULL;
synonyms = NULL;
addmacros = NULL;
varmacros = NULL;
constmacros = NULL;
fieldmacros = NULL;
funcmacros = NULL;
}
Static int readrc(rcname, need)
char *rcname;
int need;
{
FILE *rc;
char buf[500], *cp, *cp2;
long val = 0;
int i;
Strlist *sl;
rc = fopen(rcname, "r");
if (!rc) {
if (need)
perror(rcname);
return 0;
}
while (fgets(buf, 500, rc)) {
cp = my_strtok(buf, " =\t\n");
if (cp && *cp != '#') {
upc(cp);
i = numparams;
while (--i >= 0 && strcmp(rctable[i].name, cp)) ;
if (i >= 0) {
if (rctable[i].kind != 'M') {
cp = my_strtok(NULL, " =\t\n");
if (cp && *cp == '#')
cp = NULL;
if (cp && (isdigit(*cp) || *cp == '-' || *cp == '+'))
val = atol(cp);
else
val = rctable[i].def;
}
switch (rctable[i].kind) {
case 'S':
*((short *)rctable[i].ptr) = val;
break;
case 'I':
*((int *)rctable[i].ptr) = val;
break;
case 'D':
*((int *)rctable[i].ptr) =
parsedelta(cp, rctable[i].def);
break;
case 'L':
*((long *)rctable[i].ptr) = val;
break;
case 'R':
if (cp && (isdigit(*cp) || *cp == '-' || *cp == '.'))
*((double *)rctable[i].ptr) = atof(cp);
else
*((double *)rctable[i].ptr) = rctable[i].def/100.0;
break;
case 'U':
if (cp)
upc(cp);
/* fall through */
case 'C':
val = rctable[i].def;
strncpy((char *)rctable[i].ptr, cp ? cp : "", val-1);
((char *)rctable[i].ptr)[val-1] = 0;
break;
case 'F':
while (cp && *cp != '#') {
sl = strlist_append(&tweaksymbols,
format_s("*%s", cp));
sl->value = rctable[i].def;
cp = my_strtok(NULL, " \t\n");
}
break;
case 'G':
while (cp && *cp != '#') {
sl = strlist_append(&tweaksymbols, cp);
sl->value = rctable[i].def;
cp = my_strtok(NULL, " \t\n");
}
break;
case 'A':
while (cp && *cp != '#') {
strlist_insert((Strlist **)rctable[i].ptr, cp);
cp = my_strtok(NULL, " \t\n");
}
break;
case 'M':
cp = my_strtok(NULL, "\n");
if (cp) {
while (isspace(*cp)) cp++;
for (cp2 = cp; *cp2 && *cp2 != '#'; cp2++) ;
*cp2 = 0;
if (*cp) {
sl = strlist_append(&addmacros, cp);
sl->value = rctable[i].def;
}
}
break;
case 'B':
if (cp)
val = parse_breakstr(cp);
if (val != -1)
*((short *)rctable[i].ptr) = val;
break;
case 'X':
switch (rctable[i].def) {
case 1: /* strlist with string values */
if (cp) {
sl = strlist_append((Strlist **)rctable[i].ptr, cp);
cp = my_strtok(NULL, " =\t\n");
if (cp && *cp != '#')
sl->value = (long)stralloc(cp);
}
break;
case 2: /* Include */
if (cp)
readrc(format_s(cp, infname), 1);
break;
case 3: /* Synonym */
if (cp) {
sl = strlist_append(&synonyms, cp);
cp = my_strtok(NULL, " =\t\n");
if (cp && *cp != '#')
sl->value = (long)stralloc(cp);
}
break;
}
}
} else
fprintf(stderr, "warning: can't understand %s in %s\n", cp, rcname);
}
}
fclose(rc);
return 1;
}
Static void postrc()
{
int longbits;
unsigned long val;
which_unix = UNIX_ANY;
if (!strcmp(target, "CHIPMUNK") ||
!strcmp(target, "HPUX-300") ||
!strcmp(target, "SUN-68K") ||
!strcmp(target, "BSD-VAX")) {
signedchars = 1;
sizeof_char = 8;
sizeof_short = 16;
sizeof_int = sizeof_long = sizeof_pointer = 32;
sizeof_enum = 32;
sizeof_float = 32;
sizeof_double = 64;
if (!strcmp(target, "CHIPMUNK") ||
!strcmp(target, "HPUX-300"))
which_unix = UNIX_SYSV;
else
which_unix = UNIX_BSD;
} else if (!strcmp(target, "LSC-MAC")) {
signedchars = 1;
if (prototypes < 0)
prototypes = 1;
if (fullprototyping < 0)
fullprototyping = 0;
if (voidstar < 0)
voidstar = 1;
sizeof_char = 8;
sizeof_short = sizeof_int = 16;
sizeof_long = sizeof_pointer = 32;
} else if (!strcmp(target, "BSD")) {
which_unix = UNIX_BSD;
} else if (!strcmp(target, "SYSV")) {
which_unix = UNIX_SYSV;
} else if (*target) {
fprintf(stderr, "p2c: warning: don't understand target name %s\n", target);
}
if (ansiC > 0) {
if (sprintf_value < 0)
sprintf_value = 0;
if (castnull < 0)
castnull = 0;
}
if (useenum < 0)
useenum = (ansiC != 0) ? 1 : 0;
if (void_args < 0)
void_args = (ansiC > 0 && prototypes != 0) ? 1 : 0;
if (prototypes < 0)
prototypes = (cplus > 0) ? 2 : (ansiC > 0) ? 1 : 0;
if (prototypes == 0)
fullprototyping = 0;
else if (fullprototyping < 0)
fullprototyping = 1;
if (useAnyptrMacros < 0)
useAnyptrMacros = (ansiC > 0 || cplus > 0) ? 2 : 1;
if (usePPMacros < 0)
usePPMacros = (ansiC > 0 || cplus > 0) ? 0 : 2;
if (voidstar < 0)
voidstar = (ansiC > 0 || cplus > 0) ? 1 : 0;
if (hassignedchar < 0)
hassignedchar = (ansiC > 0) ? 1 : 0;
if (useconsts < 0)
useconsts = (ansiC > 0 || cplus > 0) ? 1 : 0;
if (copystructs < 0)
copystructs = (ansiC != 0 || cplus > 0) ? 3 : 0;
if (copystructfuncs < 0)
copystructfuncs = (ansiC > 0 || cplus > 0) ? 0 : 1;
if (starfunctions < 0)
starfunctions = (ansiC > 0) ? 0 : 1;
if (variablearrays < 0)
variablearrays = (ansiC > 1) ? 1 : 0;
if (initpacstrings < 0)
initpacstrings = (ansiC > 0) ? 1 : 0;
if (*memcpyname) {
if (ansiC > 0 || which_unix == UNIX_SYSV)
strcpy(memcpyname, "memcpy");
else if (which_unix == UNIX_BSD)
strcpy(memcpyname, "bcopy");
}
sizeof_integer = (sizeof_int >= 32) ? sizeof_int : sizeof_long;
integername = (sizeof_int >= 32) ? "int" : "long";
if (sizeof_integer && sizeof_integer < 32)
fprintf(stderr, "Warning: long integers have less than 32 bits\n");
if (sizeof_int >= 32 && sizeof_long > sizeof_int && prototypes == 0)
fprintf(stderr, "Warning: translated code assumes int and long are the same");
if (setbits < 0)
setbits = (sizeof_integer > 0) ? sizeof_integer : 32;
ucharname = (*name_UCHAR) ? name_UCHAR :
(signedchars == 0) ? "char" : "unsigned char";
scharname = (*name_SCHAR) ? name_SCHAR :
(signedchars == 1) ? "char" :
(useAnyptrMacros == 1) ? "Signed char" : "signed char";
for (longbits = 1, val = LONG_MAX; val >>= 1; longbits++) ;
if (sizeof_char) {
if (sizeof_char < 8 && ansiC > 0)
fprintf(stderr, "Warning: chars have less than 8 bits\n");
if (sizeof_char > longbits) {
min_schar = LONG_MIN;
max_schar = LONG_MAX;
} else {
min_schar = - (1<<(sizeof_char-1));
max_schar = (1<<(sizeof_char-1)) - 1;
}
if (sizeof_char >= longbits)
max_uchar = LONG_MAX;
else
max_uchar = (1<<sizeof_char) - 1;
} else {
min_schar = -128; /* Ansi-required minimum maxima */
max_schar = 127;
max_uchar = 255;
}
if (sizeof_short) {
if (sizeof_short < 16 && ansiC > 0)
fprintf(stderr, "Warning: shorts have less than 16 bits\n");
if (sizeof_short > longbits) {
min_sshort = LONG_MIN;
max_sshort = LONG_MAX;
} else {
min_sshort = - (1<<(sizeof_short-1));
max_sshort = (1<<(sizeof_short-1)) - 1;
}
if (sizeof_short >= longbits)
max_ushort = LONG_MAX;
else
max_ushort = (1<<sizeof_short) - 1;
} else {
min_sshort = -32768; /* Ansi-required minimum maxima */
max_sshort = 32767;
max_ushort = 65535;
}
if (symcase < 0)
symcase = 1;
if (smallsetconst == -2)
smallsetconst = (*name_SETBITS) ? -1 : 1;
hpux_lang = 0;
if (!strcmp(language, "TURBO")) {
which_lang = LANG_TURBO;
} else if (!strcmp(language, "UCSD")) {
which_lang = LANG_UCSD;
} else if (!strcmp(language, "MPW")) {
which_lang = LANG_MPW;
} else if (!strcmp(language, "HPUX") || !strcmp(language, "HP-UX")) {
which_lang = LANG_HP;
hpux_lang = 1;
} else if (!strcmp(language, "OREGON")) {
which_lang = LANG_OREGON;
} else if (!strcmp(language, "VAX") || !strcmp(language, "VMS")) {
which_lang = LANG_VAX;
} else if (!strncmp(language, "MODULA", 6)) {
which_lang = LANG_MODULA;
} else if (!strncmp(language, "BERK", 4) ||
!strcmp(language, "SUN")) {
which_lang = LANG_BERK;
} else {
if (*language && strcmp(language, "HP") && strcmp(language, "MODCAL"))
fprintf(stderr, "Warning: Language %s not recognized, using HP\n", language);
which_lang = LANG_HP;
}
if (modula2 < 0)
modula2 = (which_lang == LANG_MODULA) ? 1 : 0;
if (pascalcasesens < 0)
pascalcasesens = (which_lang == LANG_MODULA) ? 2 :
(which_lang == LANG_BERK) ? 3 : 0;
if (implementationmodules < 0)
implementationmodules = (which_lang == LANG_VAX) ? 1 : 0;
if (integer16 < 0)
integer16 = (which_lang == LANG_TURBO ||
which_lang == LANG_MPW) ? 1 : 0;
if (doublereals < 0)
doublereals = (hpux_lang ||
which_lang == LANG_OREGON ||
which_lang == LANG_VAX) ? 0 : 1;
if (pascalenumsize < 0)
pascalenumsize = (which_lang == LANG_HP) ? 16 : 8;
if (storefilenames < 0)
storefilenames = (which_lang == LANG_TURBO) ? 1 : 0;
if (charfiletext < 0)
charfiletext = (which_lang == LANG_BERK) ? 1 : 0;
if (readwriteopen < 0)
readwriteopen = (which_lang == LANG_TURBO) ? 1 : 0;
if (literalfilesflag < 0)
literalfilesflag = (which_lang == LANG_BERK) ? 2 : 0;
if (newlinespace < 0)
newlinespace = (which_lang == LANG_TURBO) ? 0 : 1;
if (nestedcomments < 0)
nestedcomments = (which_lang == LANG_TURBO ||
which_lang == LANG_MPW ||
which_lang == LANG_UCSD ||
which_lang == LANG_BERK) ? 2 : 0;
if (importall < 0)
importall = (which_lang == LANG_HP) ? 1 : 0;
if (seek_base < 0)
seek_base = (which_lang == LANG_TURBO ||
which_lang == LANG_MPW ||
which_lang == LANG_UCSD) ? 0 : 1;
if (unsignedchar < 0 && signedchars == 0)
unsignedchar = 2;
if (hasstaticlinks < 0)
hasstaticlinks = (which_lang == LANG_HP) ? 1 : 0;
if (dollar_idents < 0)
dollar_idents = (which_lang == LANG_OREGON ||
which_lang == LANG_VAX) ? 1 : 0;
if (ignorenonalpha < 0)
ignorenonalpha = (which_lang == LANG_UCSD) ? 1 : 0;
if (stringtrunclimit < 0)
stringtrunclimit = (which_lang == LANG_TURBO) ? 80 : 0;
if (defaultsetsize < 0)
defaultsetsize = (which_lang == LANG_VAX) ? 256 :
(which_lang == LANG_BERK) ? 128 :
(which_lang == LANG_MPW) ? 2040 : 8192;
if (enumbyte < 0)
enumbyte = (which_lang == LANG_HP) ? 0 : 1;
if (!*filenamefilter && (which_lang == LANG_OREGON ||
which_lang == LANG_BERK))
strcpy(filenamefilter, "P_trimname");
charname = (useAnyptrMacros) ? "Char" :
(unsignedchar == 1) ? ucharname :
(unsignedchar == 0) ? scharname : "char";
if (!*memcpyname)
strcpy(memcpyname, "memcpy");
if (!*mallocname)
strcpy(mallocname, "malloc");
if (!*freename)
strcpy(freename, "free");
fix_parameters();
}
void saveoldfile(fname)
char *fname;
{
#if defined(unix) || defined(__unix) || defined(CAN_LINK)
(void) unlink(format_s("%s~", fname));
if (link(fname, format_s("%s~", fname)) == 0)
(void) unlink(fname);
#endif
}
#ifndef __STDC__
# ifdef NO_GETENV
# define getenv(x) NULL
# else
extern char *getenv PP((char *));
# endif
#endif
Static long starting_time;
Static void openlogfile()
{
char *name, *uname;
if (*codefname == '<')
name = format_ss(logfnfmt, infname, infname);
else
name = format_ss(logfnfmt, infname, codefname);
if (!name)
name = format_s("%s.log", codefname);
saveoldfile(name);
logf = fopen(name, "w");
if (logf) {
fprintf(logf, "\nTranslation of %s to %s by p2c %s\n",
infname, codefname, P2C_VERSION);
fprintf(logf, "Translated");
uname = getenv("USER");
if (uname)
fprintf(logf, " by %s", uname);
time(&starting_time);
fprintf(logf, " on %s", ctime(&starting_time));
fprintf(logf, "\n\n");
} else {
perror(name);
verbose = 0;
}
}
void closelogfile()
{
long ending_time;
if (logf) {
fprintf(logf, "\n\n");
#if defined(unix) || defined(__unix)
fprintf(logf, "Total memory used: %ld bytes.\n", (long)sbrk(0));
#endif
time(&ending_time);
fprintf(logf, "Processed %d source lines in %ld:%ld seconds.\n",
inf_ltotal,
(ending_time - starting_time) / 60,
(ending_time - starting_time) % 60);
fprintf(logf, "\n\nTranslation completed on %s", ctime(&ending_time));
fclose(logf);
}
}
void showinitfile()
{
FILE *f;
int ch;
char *name;
name = format_s("%H/%s", "p2crc");
printf("# Copy of file %%H/p2crc => %s:\n\n", name);
f = fopen(name, "r");
if (!f) {
perror(name);
exit(1);
}
while ((ch = getc(f)) != EOF)
putchar(ch);
fclose(f);
exit(0);
}
void usage()
{
fprintf(stderr, "usage: p2c [options] file [modulename] [-h file.h] [-o file.c]\n");
exit(EXIT_FAILURE);
}
int main(argc, argv)
int argc;
char **argv;
{
int numsearch;
char *searchlist[50];
char infnbuf[200], codefnbuf[200], hdrfnbuf[200], *cp;
Symbol *sp;
Strlist *sl;
int i, nobuffer = 0, savequiet;
i = 0;
while (i < argc && strcmp(argv[i], "-H")) i++;
if (i < argc-1)
p2c_home = argv[i+1];
else {
cp = getenv("P2C_HOME");
if (cp)
p2c_home = cp;
}
init_stuff();
i = 0;
while (i < argc && strcmp(argv[i], "-i")) i++;
if (i < argc)
showinitfile();
initrc();
setup_dir();
infname = infnbuf;
*infname = 0;
i = 0;
while (i < argc && argv[i][0] == '-') i++;
if (i >= argc)
strcpy(infname, argv[i]);
i = 0;
while (i < argc && strcmp(argv[i], "-v")) i++;
if (i >= argc) {
cp = getenv("P2CRC");
if (cp)
readrc(cp, 1);
else
readrc(format_s("%H/%s", "p2crc"), 1);
}
i = 0;
while (i < argc && strcmp(argv[i], "-c")) i++;
if (i < argc-1) {
if (strcmp(argv[i+1], "-"))
readrc(argv[i+1], 1);
} else
if (!readrc("p2crc", 0))
readrc(".p2crc", 0);
codefname = codefnbuf;
*codefname = 0;
hdrfname = hdrfnbuf;
*hdrfname = 0;
requested_module = NULL;
found_module = 0;
error_crash = 0;
#ifdef CONSERVE_MEMORY
conserve_mem = CONSERVE_MEMORY;
#else
conserve_mem = 1;
#endif
regression = 0;
verbose = 0;
partialdump = 1;
numsearch = 0;
argc--, argv++;
while (argc > 0) {
if (**argv == '-' && (*argv)[1]) {
if (!strcmp(*argv, "-a")) {
ansiC = 1;
} else if (argv[0][1] == 'L') {
if (strlen(*argv) == 2 && argc > 1) {
strcpy(language, ++*argv);
--argc;
} else
strcpy(language, *argv + 2);
upc(language);
} else if (!strcmp(*argv, "-q")) {
quietmode = 1;
} else if (!strcmp(*argv, "-o")) {
if (*codefname || --argc <= 0)
usage();
strcpy(codefname, *++argv);
} else if (!strcmp(*argv, "-h")) {
if (*hdrfname || --argc <= 0)
usage();
strcpy(hdrfname, *++argv);
} else if (!strcmp(*argv, "-s")) {
if (--argc <= 0)
usage();
cp = *++argv;
if (!strcmp(cp, "-"))
librfiles = NULL;
else
searchlist[numsearch++] = cp;
} else if (!strcmp(*argv, "-c")) {
if (--argc <= 0)
usage();
argv++;
/* already done above */
} else if (!strcmp(*argv, "-v")) {
/* already done above */
} else if (!strcmp(*argv, "-H")) {
/* already done above */
} else if (argv[0][1] == 'I') {
if (strlen(*argv) == 2 && argc > 1) {
strlist_append(&importdirs, ++*argv);
--argc;
} else
strlist_append(&importdirs, *argv + 2);
} else if (argv[0][1] == 'p') {
if (strlen(*argv) == 2)
showprogress = 25;
else
showprogress = atoi(*argv + 2);
nobuffer = 1;
} else if (!strcmp(*argv, "-e")) {
copysource++;
} else if (!strcmp(*argv, "-t")) {
tokentrace++;
} else if (!strcmp(*argv, "-x")) {
error_crash++;
} else if (argv[0][1] == 'E') {
if (strlen(*argv) == 2)
maxerrors = 0;
else
maxerrors = atoi(*argv + 2);
} else if (!strcmp(*argv, "-F")) {
partialdump = 0;
} else if (argv[0][1] == 'd') {
nobuffer = 1;
if (strlen(*argv) == 2)
debug = 1;
else
debug = atoi(*argv + 2);
} else if (argv[0][1] == 'B') {
if (strlen(*argv) == 2)
i = 1;
else
i = atoi(*argv + 2);
if (argc == 2 &&
strlen(argv[1]) > 2 &&
!strcmp(argv[1] + strlen(argv[1]) - 2, ".c")) {
testlinebreaker(i, argv[1]);
exit(EXIT_SUCCESS);
} else
testlinebreaker(i, NULL);
} else if (argv[0][1] == 'C') {
if (strlen(*argv) == 2)
cmtdebug = 1;
else
cmtdebug = atoi(*argv + 2);
} else if (!strcmp(*argv, "-R")) {
regression = 1;
} else if (argv[0][1] == 'V') {
if (strlen(*argv) == 2)
verbose = 1;
else
verbose = atoi(*argv + 2);
} else if (argv[0][1] == 'M') {
if (strlen(*argv) == 2)
conserve_mem = 1;
else
conserve_mem = atoi(*argv + 2);
} else
usage();
} else if (!*infname) {
strcpy(infname, *argv);
} else if (!requested_module) {
requested_module = stralloc(*argv);
} else
usage();
argc--, argv++;
}
if (requested_module && !*codefname)
strcpy(codefname, format_ss(modulefnfmt, infname, requested_module));
if (*infname && strcmp(infname, "-")) {
if (strlen(infname) > 2 &&
!strcmp(infname + strlen(infname) - 2, ".c")) {
fprintf(stderr, "What is wrong with this picture?\n");
exit(EXIT_FAILURE);
}
inf = fopen(infname, "r");
if (!inf) {
perror(infname);
exit(EXIT_FAILURE);
}
if (!*codefname)
strcpy(codefname, format_s(codefnfmt, infname));
} else {
strcpy(infname, "<stdin>");
inf = stdin;
if (!*codefname)
strcpy(codefname, "-");
}
if (strcmp(codefname, "-")) {
saveoldfile(codefname);
codef = fopen(codefname, "w");
if (!codef) {
perror(codefname);
exit(EXIT_FAILURE);
}
fprintf(codef, "/* Output from p2c, the Pascal-to-C translator */\n");
} else {
strcpy(codefname, "<stdout>");
codef = stdout;
}
if (nobuffer)
setbuf(codef, NULL); /* for debugging */
outf = codef;
outf_lnum = 1;
logf = NULL;
if (verbose)
openlogfile();
setup_complete = 0;
init_lex();
leadingcomments();
postrc();
setup_comment(); /* must call this first */
setup_lex(); /* must call this second */
setup_out();
setup_decl(); /* must call *after* setup_lex() */
setup_parse();
setup_funcs();
for (sl = tweaksymbols; sl; sl = sl->next) {
cp = sl->s;
if (*cp == '*') {
cp++;
if (!pascalcasesens)
upc(cp);
}
sp = findsymbol(cp);
if (sl->value & FUNCBREAK)
sp->flags &= ~FUNCBREAK;
sp->flags |= sl->value;
}
strlist_empty(&tweaksymbols);
for (sl = synonyms; sl; sl = sl->next) {
if (!pascalcasesens)
upc(sl->s);
sp = findsymbol(sl->s);
sp->flags |= SSYNONYM;
if (sl->value) {
if (!pascalcasesens)
upc((char *)sl->value);
strlist_append(&sp->symbolnames, "===")->value =
(long)findsymbol((char *)sl->value);
} else
strlist_append(&sp->symbolnames, "===")->value = 0;
}
strlist_empty(&synonyms);
for (sl = addmacros; sl; sl = sl->next) {
defmacro(sl->s, sl->value, "<macro>", 0);
}
strlist_empty(&addmacros);
handle_nameof();
setup_complete = 1;
savequiet = quietmode;
quietmode = 1;
for (sl = librfiles; sl; sl = sl->next)
(void)p_search(format_none(sl->s), "pas", 0);
for (i = 0; i < numsearch; i++)
(void)p_search(format_none(searchlist[i]), "pas", 1);
quietmode = savequiet;
p_program();
end_source();
flushcomments(NULL, -1, -1);
showendnotes();
check_unused_macros();
printf("\n");
if (!showprogress)
fprintf(stderr, "\n");
output("\n");
if (requested_module && !found_module)
error(format_s("Module \"%s\" not found in file", requested_module));
if (codef != stdout)
output("\n\n/* End. */\n");
if (inf != stdin)
fclose(inf);
if (codef != stdout)
fclose(codef);
closelogfile();
mem_summary();
if (!quietmode)
fprintf(stderr, "Translation completed.\n");
exit(EXIT_SUCCESS);
}
int outmem()
{
fprintf(stderr, "p2c: Out of memory!\n");
exit(EXIT_FAILURE);
}
#if !defined(NO_ISBOGUS) && (defined(mc68000) || defined(m68k) || defined(vax))
int ISBOGUS(p)
char *p;
{
unsigned long ip = (unsigned long)p;
if (ip < 0) {
if (ip < (unsigned long)&ip)
return 1; /* below the start of the stack */
} else if (ip >= 512) {
if (ip > (unsigned long)sbrk(0))
return 1; /* past the end of memory */
} else
return 1;
return 0;
}
#else
#define ISBOGUS(p) 0
#endif
char *meaningkindname(kind)
enum meaningkind kind;
{
#ifdef HASDUMPS
if ((unsigned int)kind < (unsigned int)MK_LAST)
return meaningkindnames[(int) kind];
else
#endif /*HASDUMPS*/
return format_d("<meaning %d>", (int) kind);
}
char *typekindname(kind)
enum typekind kind;
{
#ifdef HASDUMPS
if ((unsigned int)kind < (unsigned int)TK_LAST)
return typekindnames[(int) kind];
else
#endif /*HASDUMPS*/
return format_d("<type %d>", (int) kind);
}
char *exprkindname(kind)
enum exprkind kind;
{
#ifdef HASDUMPS
if ((unsigned int)kind < (unsigned int)EK_LAST)
return exprkindnames[(int) kind];
else
#endif /*HASDUMPS*/
return format_d("<expr %d>", (int) kind);
}
char *stmtkindname(kind)
enum stmtkind kind;
{
#ifdef HASDUMPS
if ((unsigned int)kind < (unsigned int)SK_LAST)
return stmtkindnames[(int) kind];
else
#endif /*HASDUMPS*/
return format_d("<stmt %d>", (int) kind);
}
void dumptype(tp)
Type *tp;
{
if (!tp) {
fprintf(outf, "<NULL>\n");
return;
}
if (ISBOGUS(tp)) {
fprintf(outf, "0x%lX\n", tp);
return;
}
fprintf(outf, " Type %lx, kind=%s", tp, typekindname(tp->kind));
#ifdef HASDUMPS
fprintf(outf, ", meaning=%lx, basetype=%lx, indextype=%lx\n",
tp->meaning, tp->basetype, tp->indextype);
tp->dumped = 1;
if (tp->basetype)
dumptype(tp->basetype);
if (tp->indextype)
dumptype(tp->indextype);
#else
fprintf(outf, "\n");
#endif /*HASDUMPS*/
}
void dumpmeaning(mp)
Meaning *mp;
{
if (!mp) {
fprintf(outf, "<NULL>\n");
return;
}
if (ISBOGUS(mp)) {
fprintf(outf, "0x%lX\n", mp);
return;
}
fprintf(outf, " Meaning %lx, name=%s, kind=%s", mp, ((mp->name) ? mp->name : "<null>"),
meaningkindname(mp->kind));
#ifdef HASDUMPS
fprintf(outf, ", ctx=%lx, cbase=%lx, cnext=%lx, type=%lx\n",
mp->ctx, mp->cbase, mp->cnext, mp->type);
if (mp->type && !mp->type->dumped)
dumptype(mp->type);
mp->dumped = 1;
#else
fprintf(outf, "\n");
#endif /*HASDUMPS*/
}
void dumpsymtable(sym)
Symbol *sym;
{
Meaning *mp;
if (sym) {
dumpsymtable(sym->left);
#ifdef HASDUMPS
if ((sym->mbase && !sym->mbase->dumped) ||
(sym->fbase && !sym->fbase->dumped))
#endif
{
fprintf(outf, "Symbol %s:\n", sym->name);
for (mp = sym->mbase; mp; mp = mp->snext)
dumpmeaning(mp);
for (mp = sym->fbase; mp; mp = mp->snext)
dumpmeaning(mp);
fprintf(outf, "\n");
}
dumpsymtable(sym->right);
}
}
void dumptypename(tp, waddr)
Type *tp;
int waddr;
{
#ifdef HASDUMPS
if (!tp) {
fprintf(outf, "<NULL>");
return;
}
if (ISBOGUS(tp)) {
fprintf(outf, "0x%lX", tp);
return;
}
if (tp == tp_int) fprintf(outf, "I");
else if (tp == tp_sint) fprintf(outf, "SI");
else if (tp == tp_uint) fprintf(outf, "UI");
else if (tp == tp_integer) fprintf(outf, "L");
else if (tp == tp_unsigned) fprintf(outf, "UL");
else if (tp == tp_char) fprintf(outf, "C");
else if (tp == tp_schar) fprintf(outf, "UC");
else if (tp == tp_uchar) fprintf(outf, "SC");
else if (tp == tp_boolean) fprintf(outf, "B");
else if (tp == tp_longreal) fprintf(outf, "R");
else if (tp == tp_real) fprintf(outf, "F");
else if (tp == tp_anyptr) fprintf(outf, "A");
else if (tp == tp_void) fprintf(outf, "V");
else if (tp == tp_text) fprintf(outf, "T");
else if (tp == tp_bigtext) fprintf(outf, "BT");
else if (tp == tp_sshort) fprintf(outf, "SS");
else if (tp == tp_ushort) fprintf(outf, "US");
else if (tp == tp_abyte) fprintf(outf, "AB");
else if (tp == tp_sbyte) fprintf(outf, "SB");
else if (tp == tp_ubyte) fprintf(outf, "UB");
else if (tp == tp_str255) fprintf(outf, "S");
else if (tp == tp_strptr) fprintf(outf, "SP");
else if (tp == tp_charptr) fprintf(outf, "CP");
else if (tp == tp_smallset) fprintf(outf, "SMS");
else if (tp == tp_proc) fprintf(outf, "PR");
else if (tp == tp_jmp_buf) fprintf(outf, "JB");
else {
if (tp->meaning && !ISBOGUS(tp->meaning) &&
tp->meaning->name && !ISBOGUS(tp->meaning->name) &&
tp->meaning->name[0]) {
fprintf(outf, "%s", tp->meaning->name);
if (tp->dumped)
return;
fprintf(outf, "=");
waddr = 1;
}
if (waddr) {
fprintf(outf, "%lX", tp);
if (tp->dumped)
return;
fprintf(outf, ":");
tp->dumped = 1;
}
switch (tp->kind) {
case TK_STRING:
fprintf(outf, "Str");
if (tp->structdefd)
fprintf(outf, "Conf");
break;
case TK_SUBR:
dumptypename(tp->basetype, 0);
break;
case TK_POINTER:
fprintf(outf, "^");
dumptypename(tp->basetype, 0);
break;
case TK_SMALLARRAY:
fprintf(outf, "Sm");
/* fall through */
case TK_ARRAY:
fprintf(outf, "Ar");
if (tp->structdefd)
fprintf(outf, "Conf");
fprintf(outf, "{");
dumptypename(tp->indextype, 0);
fprintf(outf, "}");
if (tp->smin) {
fprintf(outf, "Skip(");
dumpexpr(tp->smin);
fprintf(outf, ")");
}
if (tp->smax) {
fprintf(outf, "/");
if (!ISBOGUS(tp->smax))
dumptypename(tp->smax->val.type, 0);
fprintf(outf, "{%d%s}", tp->escale,
tp->issigned ? "S" : "U");
}
fprintf(outf, ":");
dumptypename(tp->basetype, 0);
break;
case TK_SMALLSET:
fprintf(outf, "Sm");
/* fall through */
case TK_SET:
fprintf(outf, "Set{");
dumptypename(tp->indextype, 0);
fprintf(outf, "}");
break;
case TK_FILE:
fprintf(outf, "File{");
dumptypename(tp->basetype, 0);
fprintf(outf, "}");
break;
case TK_BIGFILE:
fprintf(outf, "BigFile{");
dumptypename(tp->basetype, 0);
fprintf(outf, "}");
break;
case TK_FUNCTION:
fprintf(outf, "Func");
if (tp->issigned)
fprintf(outf, "Link");
fprintf(outf, "{");
dumptypename(tp->basetype, 0);
fprintf(outf, "}");
break;
case TK_CPROCPTR:
fprintf(outf, "C");
/* fall through */
case TK_PROCPTR:
fprintf(outf, "Proc%d{", tp->escale);
dumptypename(tp->basetype, 0);
fprintf(outf, "}");
break;
default:
fprintf(outf, "%s", typekindname(tp->kind));
break;
}
if (tp->kind != TK_ARRAY && tp->kind != TK_SMALLARRAY &&
(tp->smin || tp->smax)) {
fprintf(outf, "{");
dumpexpr(tp->smin);
fprintf(outf, "..");
dumpexpr(tp->smax);
fprintf(outf, "}");
}
}
#else
fprintf(outf, "%lX", tp);
#endif
}
void dumptypename_file(f, tp)
FILE *f;
Type *tp;
{
FILE *save = outf;
outf = f;
dumptypename(tp, 1);
outf = save;
}
void dumpexpr(ex)
Expr *ex;
{
int i;
Type *type;
char *name;
if (!ex) {
fprintf(outf, "<NULL>");
return;
}
if (ISBOGUS(ex)) {
fprintf(outf, "0x%lX", ex);
return;
}
if (ex->kind == EK_CONST && ex->val.type == tp_integer &&
ex->nargs == 0 && !ex->val.s) {
fprintf(outf, "%ld", ex->val.i);
return;
}
if (ex->kind == EK_LONGCONST && ex->val.type == tp_integer &&
ex->nargs == 0 && !ex->val.s) {
fprintf(outf, "%ldL", ex->val.i);
return;
}
name = exprkindname(ex->kind);
if (!strncmp(name, "EK_", 3))
name += 3;
fprintf(outf, "%s", name);
#ifdef HASDUMPS
type = ex->val.type;
fprintf(outf, "/");
dumptypename(type, 1);
if (ex->val.i) {
switch (ex->kind) {
case EK_VAR:
case EK_FUNCTION:
case EK_CTX:
if (ISBOGUS(ex->val.i))
fprintf(outf, "[0x%lX]", ex->val.i);
else
fprintf(outf, "[\"%s\"]", ((Meaning *)ex->val.i)->name);
break;
default:
fprintf(outf, "[i=%ld]", ex->val.i);
break;
}
}
if (ISBOGUS(ex->val.s))
fprintf(outf, "[0x%lX]", ex->val.s);
else if (ex->val.s) {
switch (ex->kind) {
case EK_BICALL:
case EK_NAME:
case EK_DOT:
fprintf(outf, "[s=\"%s\"]", ex->val.s);
break;
default:
switch (ex->val.type ? ex->val.type->kind : TK_VOID) {
case TK_STRING:
fprintf(outf, "[s=%s]", makeCstring(ex->val.s, ex->val.i));
break;
case TK_REAL:
fprintf(outf, "[s=%s]", ex->val.s);
break;
default:
fprintf(outf, "[s=%lx]", ex->val.s);
}
break;
}
}
if (ex->nargs > 0) {
fprintf(outf, "(");
if (ex->nargs < 10) {
for (i = 0; i < ex->nargs; i++) {
if (i)
fprintf(outf, ", ");
dumpexpr(ex->args[i]);
}
} else
fprintf(outf, "...");
fprintf(outf, ")");
}
#endif
}
void dumpexpr_file(f, ex)
FILE *f;
Expr *ex;
{
FILE *save = outf;
outf = f;
dumpexpr(ex);
outf = save;
}
void innerdumpstmt(sp, indent)
Stmt *sp;
int indent;
{
#ifdef HASDUMPS
if (!sp) {
fprintf(outf, "<NULL>\n");
return;
}
while (sp) {
if (ISBOGUS(sp)) {
fprintf(outf, "0x%lX\n", sp);
return;
}
fprintf(outf, "%s", stmtkindname(sp->kind));
if (sp->exp1) {
fprintf(outf, ", exp1=");
dumpexpr(sp->exp1);
}
if (sp->exp2) {
fprintf(outf, ", exp2=");
dumpexpr(sp->exp2);
}
if (sp->exp3) {
fprintf(outf, ", exp3=");
dumpexpr(sp->exp3);
}
fprintf(outf, "\n");
if (sp->stm1) {
fprintf(outf, "%*sstm1=", indent, "");
innerdumpstmt(sp->stm1, indent+5);
}
if (sp->stm2) {
fprintf(outf, "%*sstm2=", indent, "");
innerdumpstmt(sp->stm2, indent+5);
}
sp = sp->next;
if (sp) {
if (indent > 5)
fprintf(outf, "%*s", indent-5, "");
fprintf(outf, "next=");
}
}
#endif
}
void dumpstmt(sp, indent)
Stmt *sp;
int indent;
{
fprintf(outf, "%*s", indent, "");
innerdumpstmt(sp, indent);
}
void dumpstmt_file(f, sp)
FILE *f;
Stmt *sp;
{
FILE *save = outf;
Stmt *savenext = NULL;
outf = f;
if (sp) {
savenext = sp->next;
sp->next = NULL;
}
dumpstmt(sp, 5);
if (sp)
sp->next = savenext;
outf = save;
}
void wrapup()
{
int i;
for (i = 0; i < SYMHASHSIZE; i++)
dumpsymtable(symtab[i]);
}
void mem_summary()
{
#ifdef TEST_MALLOC
printf("Summary of memory allocated but not freed:\n");
printf("Total bytes = %d of %d\n", final_bytes, total_bytes);
printf("Expressions = %d of %d\n", final_exprs, total_exprs);
printf("Meanings = %d of %d (%d of %d)\n",
final_meanings, total_meanings,
final_meanings / sizeof(Meaning),
total_meanings / sizeof(Meaning));
printf("Strings = %d of %d\n", final_strings, total_strings);
printf("Symbols = %d of %d\n", final_symbols, total_symbols);
printf("Types = %d of %d (%d of %d)\n", final_types, total_types,
final_types / sizeof(Type), total_types / sizeof(Type));
printf("Statements = %d of %d (%d of %d)\n", final_stmts, total_stmts,
final_stmts / sizeof(Stmt), total_stmts / sizeof(Stmt));
printf("Strlists = %d of %d\n", final_strlists, total_strlists);
printf("Literals = %d of %d\n", final_literals, total_literals);
printf("Ctxstacks = %d of %d\n", final_ctxstacks, total_ctxstacks);
printf("Temp vars = %d of %d\n", final_tempvars, total_tempvars);
printf("Input recs = %d of %d\n", final_inprecs, total_inprecs);
printf("Parens = %d of %d\n", final_parens, total_parens);
printf("Ptr Descs = %d of %d\n", final_ptrdescs, total_ptrdescs);
printf("Other = %d of %d\n", final_misc, total_misc);
printf("\n");
#endif
}
#ifdef TEST_MALLOC
anyptr memlist;
anyptr test_malloc(size, total, final)
int size, *total, *final;
{
anyptr p;
p = malloc(size + 3*sizeof(long));
#if 1
((anyptr *)p)[0] = memlist;
memlist = p;
((long *)p)[1] = size;
((int **)p)[2] = final;
total_bytes += size;
final_bytes += size;
*total += size;
*final += size;
#endif
return (anyptr)((long *)p + 3);
}
void test_free(p)
anyptr p;
{
#if 1
final_bytes -= ((long *)p)[1-3];
*((int **)p)[2-3] -= ((long *)p)[1-3];
((long *)p)[1-3] *= -1;
#endif
}
anyptr test_realloc(p, size)
anyptr p;
int size;
{
anyptr p2;
p2 = test_malloc(size, &total_misc, &final_misc);
memcpy(p2, p, size);
test_free(p);
return p2;
}
#endif /* TEST_MALLOC */
/* End. */