⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cc.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 3 页
字号:
static
int
cfile (char *arg)
    {
    int		mainflg;		/* Set if module contains "main" */
    int		asmdflg = -2;		/* Set to result of assembly attempt */
    clock_t	startime;
    extern
    int		nsert_file (char *f, int insert_flag);
    int		save_fline;
    int		save_tline;


    if (!vrbsta)
	startime = clock();		/* Mark cpu time */

    /* 11/91 added nwarns */

    nerrors = nwarns = err_waiting = 0;	/* KAR  added err_waiting init */

    if (!files(arg))			/* If couldn't open or file is .REL, */
	return asmdflg;			/* just return. */

    if (mlist)				/* set up output file with page hdr */
	{
	opage = 0;
	outpghdr();
	}

module_loop:

    save_fline = fline;
    save_tline = tline;

    if (!prepf)
	{
	fprintf (outmsgs, "KCC: %s\n", (module_pragma) ? title : inpfmodule);

	if (outmsgs == stdout)
	    fprintf (stderr, "KCC: %s\n",
	    	    (module_pragma) ? title : inpfmodule);
	}

    syminit ();				/* Set up symbol tables */
    ppinit ();				/* Initialize the input preprocessor */
    ppdefine (npreundef,preundefs,	/*  then can do initial -U undefs */
	     npredef, predefs);		/*   and initial -D definitions */

    if (module_pragma)
	{
	fline = save_fline;		/* ppinit() reset fline */
	tline = save_tline;
	module_pragma = 0;
	lexinit ();
	module_pragma = 1;
	}
    else
	lexinit ();			/* Initialize the input lexer */

    initpar ();				/* Initialize the input parser */

    /* KAR-6/92, moved reset of -i here to handle multiple files as well */

    nsert_file (NULL,0);		/* turn off "-i" command line switch */
    dbginit ();				/* Initialize src debugger output */

    if (prepf)				/* If only preprocessor output (-E) */
	{
	passthru (stdout);		/*   send it through specially */
	fclose (in);			/*   and then close input */

#if DEBUG_KCC				/* 5/91 KCC size */
	if (debsym)
	    {
	    symdump (minsym->Snext, "external"); /* symbol table dump */
	    typedump ();
	    fclose (fsym);
	    }
#endif
	}
    else				/* Normal compilation processing */
	{
	NODE*	    n;

	/* if (module_pragma) outinit() puts title in *.mac outpreamble()*/

	outinit ();			/* Initialize assembler code output */
	module_pragma = 0;

	if (eof)
	    {
	    if (clevel >= CLEV_STRICT)
		error ("File must contain at least one external definition");
	    else
		warn ("Null source file");
	    }

	while (!eof)			/* Process each external definition */
	    {
	    savelits = 0;		/* Reset string literal pool */
	    nodeinit ();		/* Reset parse-tree node table */
	    curfn = NULL;		/* Not in any function */
	    n = extdef ();		/* parse one external definition */
					/* 2/92 may turn on module_pragma */
#if DEBUG_KCC				/* 5/91 KCC size */
	    if (debpar)
		nodedump (n);		/* Dump parse tree if debugging */
#endif

	    gencode (n);		/* Call code generator on parse tree */
	    }

	if (!module_pragma)
	    {
	    fclose (in);		/* Done with input stream, close it. */
	    curfn = NULL;		/* Not in any function */
	    fline = 0;			/* Avoid context on errs after this */
	    }

	while ((n = tntdef ()) != NULL)	/* Output remaining tentative defs */
	    {
#if DEBUG_KCC				/* 5/91 KCC size */
	    if (debpar)
		nodedump (n);
#endif

	    gencode (n);
	    nodeinit ();		/* Reset node table after each */
	    }

	if ((mainflg = mainsymp ()) != 0) /* Is "main" defined in module? */
	    strcpy (mainname, inpfmodule); /* Yes, save module name! */

	switch (abs (debcsi))
	    {
	    case KCC_DBG_SDBG :
	    case KCC_DBG_FDBG :
		savesymtab (minsym->Snext); /* generate debug symtab */
		break;


	    default:
		break;
	    }

	outdone (mainflg);		/* Output assembler postamble stuff */

	if (module_pragma)
	    goto module_loop;

	fclose (out);			/* and close assembler output file. */

#if DEBUG_KCC				/* 5/91 KCC size */
	if (debsym)
	    {
	    symdump (minsym->Snext, "external"); /* symbol table dump */
	    typedump ();
	    fclose (fsym);
	    }

	if (debpar)
	    fclose (fdeb);		/* Close parse tree debug file */

	if (debpho)
	    fclose (fpho);		/* Close peephole debug file */
#endif

	if (!nerrors && assemble)
	    asmdflg = asmb ((savofnam ? savofnam : inpfmodule),
		(char *) NULL, outfname); /* and this. */

	if ((delete && asmdflg != 0) && (!mlist))
	    remove (outfname);
	}

    if (outmsgs == stdout)
	fprintf (outmsgs, "%% KCC - %d warning%s detected\n", nwarns,
		 nwarns == 1 ? "" : "s" );

    if (nwarns)				/* Report warnings */
	fprintf (stderr, "%% KCC - %d warning%s detected\n", nwarns,
		 nwarns == 1 ? "" : "s" );

    if (nerrors)			/* Report errors */
	jmsg ("%d error%s detected", nerrors, nerrors == 1 ? "" : "s" );
    else if (!vrbsta)
	showcpu (startime);		/* or say how much cpu we used */

    return asmdflg;			/* Return assembly result */
    }

/* Auxiliary - returns true if main() was defined in this module */

static
int
mainsymp (void)
    {
    SYMBOL*	s;


    return ((s = symfidstr ("main")) != NULL && s->Sclass == SC_EXTDEF);
    }

/*
 * FILES - parse a filename argument and set up I/O streams.
 *
 *	Note that "prefname" is set up here, but not opened.
 * This is because we may not need to use it; the call to
 * "makprefile()" will do so if necessary.
 */

static
int
files (char *fname)
    {
    int		cextf;
    char*	cp;
    char	cname[FNAMESIZE];	/* Name of .C source file */
    char	rname[FNAMESIZE];	/* Name of .REL binary file */
    char	ext[FNAMESIZE];		/* Temp to hold parsed extension */


    /*
    ** Parse filename into its various pieces, mainly to get module name.
    ** As a special case, it will work to specify a device (logical) name
    ** with no filename, e.g. you can say
    **        @CC FOO:
    ** where FOO: => <DIR>NAME.C, and the module name will be FOO.
    */

    /* in __MSDOS__  fnparse() calls fnsplit() */

    if ((cp = fnparse (fname, inpfdir, inpfmodule, ext, inpfsuf)) != NULL)
	{
	jerr ("Bad filename arg (%s): \"%s\"", cp, fname);	/* Ugh */
	return 0;			/* and don't try to compile */
	}

    if (fnxisrel(ext))	/* .obj for DOS */
	return 0;

    /* Check for .C or .H extensions.  "cextf" is set if we have it. */

    cextf = (ext[0] == '.'
	     && (toupper(ext[1]) == 'C' || toupper(ext[1]) == 'H') && !ext[2]);

    /* Now compose source filename with ".C" appended if necessary */

    if (cextf)
	strcpy (cname, fname);	/* Found .C, just copy filename */
    else
	{
#if __MSDOS__
	estrcpy (estrcpy (estrcpy (estrcpy (cname,	/* Rebuild filename */
		inpfsuf), inpfdir), inpfmodule), ".c");
#else
	estrcpy (estrcpy (estrcpy (estrcpy (cname,	/* Rebuild filename */
		inpfdir), inpfmodule), ".c"), inpfsuf);
#endif
	}

    if (mlist)
	{
	int	    i;


	for (i = 0; cname[i] != '\0'; i++)
	    dspfname[i] = toupper(cname[i]);

	dspfname[i] = '\0';
	getimestr(cname);
	}

    /*
     * If the -q conditional compile flag was
     * set, we assume that we are to check the .C and .REL extensions of
     * this file to determine whether compilation is necessary.
     */

    if (condccf)
	{
	strcpy (rname, inpfmodule);		/* Make the .REL filename */
	strcat (rname, ".rel");

	if (!needcomp (cname, rname))
	    return 0;		/* Doesn't need to be compiled! */
	}

    /*
     * Now that we've figured out what the name of the file is, we can try
     * to open it.  First we try the filename as given, and if that doesn't
     * work (most likely because no .C was specified) then we try the
     * one we constructed by adding .C.
     */

    strcpy (inpfname, fname);		/* Try filename as given */

#if __MSDOS__				/* FW 2A(47) */
    in = fopen (inpfname, "r");
#else
    switch (sourcebytewidth)		/* FW 2A(47) */
	{
	case 8 :
	    in = fopen (inpfname, "r8");
	    break;

	case 9 :
	    in = fopen (inpfname, "r9");
	    break;

	default :
	    in = fopen (inpfname, "r");
	    break;
	}
#endif
    
    if (in == NULL)
	{
	strcpy (inpfname, cname);	/* then constructed filename */

#if __MSDOS__				/* FW 2A(47) */
	in = fopen (inpfname, "r");
#else
	switch (sourcebytewidth)	/* FW 2A(47) */
	    {
	    case 8 :
		in = fopen (inpfname, "r8");
		break;

	    case 9 :
		in = fopen (inpfname, "r9");
		break;

	    default :
		in = fopen (inpfname, "r");
		break;
	    }
#endif

	if (in == NULL)
	    {
	    errfopen("input", inpfname);
	    return 0;
	    }
	}

#if DEBUG_KCC		/* 5/91 KCC size */
    /* Compose symbol table dump output filename, if desired */

    if (debsym)
	{
	strcpy (symfname, inpfmodule);
	strcat (symfname, ".cym");

	if ((fsym = fopen(symfname, "w")) == NULL)
	    {
	    errfopen("symbol table", symfname);
	    return 0;
	    }
	}
#endif

    /* If we are only doing pre-processing, then no other filenames are
    ** needed, and we can return now.
    */
    if (prepf)
	return 1;

    /*
    ** The output file is merely ".mac" etc concatenated to the stripped
    ** filename we calculated above, in the current directory.
    */

    cp = ".mac";

    if (savofnam != NULL)
	{
	char *tfnam, *ptr;

	tfnam = (char *) calloc (strlen (savofnam), sizeof(char *));
	if (tfnam == NULL)
	    jerr("Out of memory for .REL filenames\n");
	strcpy (tfnam, savofnam);
	ptr = strchr(tfnam, '.');

	if (ptr == NULL)
	    strcat (strcpy(outfname, savofnam), cp);
	else
	    {
	    *ptr = '\0';
	    strcat (strcpy(outfname, tfnam), cp);
	    }

	free (tfnam);
	}
    else
	strcat(strcpy(outfname, inpfmodule), cp); /* Compose output filename */

    if ((out = fopen(outfname, "w")) == NULL)
	{
	errfopen("output", outfname);
	return 0;
	}

    /* Now open various other debugging output files */

    if (debpar)		/* debugging output goes here */
	{
	strcpy(debfname, inpfmodule);
	strcat(debfname, ".deb");
	if ((fdeb = fopen(debfname, "w")) == NULL)
	    {
	    errfopen("parser debugging output", debfname);
	    return 0;
	    }
	}

#if DEBUG_KCC		/* 5/91 KCC size */
    if (debpho)		/* Peephole debugging output goes here */
	{
	strcpy(phofname, inpfmodule);
	strcat(phofname, ".pho");
	if ((fpho = fopen(phofname, "w")) == NULL)
	    {
	    errfopen("peephole debugging output", phofname);
	    return 0;
	    }
	}
#endif

    return 1;
}

/*
 * NEEDCOMP - Auxiliary for above.
 *	Takes source and binary filenames, returns TRUE if
 *	source needs compiling (is newer than binary).
 */

#if __MSDOS__		/* 4/92 avoid non-ANSI stat() */
#define stats stat	/* just use stat() */
#else
extern
int	    stats (char *source_fname, struct stat* statb);
#endif



static
int
needcomp (char* src, char* rel)
    {
    struct
    stat	sbuf,
		rbuf;


    if (stats(src, &sbuf) < 0)
	return 1;
			/* No source?? Try compiling anyway */
    if (stats(rel, &rbuf) < 0)
	return 1;			/* No .REL, so must compile */

    return (sbuf.st_mtime > rbuf.st_mtime);	/* Compare last mod times */
    }

/*
 * GETIMESTR - Builds time strings for mixed listing --KAR 8/90
 */

static
void
getimestr (char* src_fname)
    {
    time_t	curtime;
    time_t*	ctptr = &curtime;
    char*	tptr;
    struct
    stat	sbuf;


    stats (src_fname, &sbuf);
    curtime = time (NULL);
    tptr = ctime (ctptr);
    strcpy (comptime, tptr);

#if 0
    tptr = ctime(&sbuf.st_mtime);
    strcpy (creatime, tptr);
#endif

    strtok (comptime, "\n");
    strtok (creatime, "\n");
    }

/*
 *      show how much cpu we used
 */

static
void
showcpu (clock_t otim)
    {
    float	secs;


    secs = (float) (clock() - otim) / CLOCKS_PER_SEC;	/* Find # secs used */

    if (outmsgs == stdout)	/* 8/91 -s  PPS 4298 */
	fprintf (outmsgs, "Processed %d lines in %.2f CPU seconds "
		 "(%ld lines/min)\n", (int) tline, secs,
		 (INT)((tline*60.0)/secs));

    fprintf (stderr,"Processed %d lines in %.2f CPU seconds (%ld lines/min)\n",
	     (int) tline, secs, (INT)((tline*60.0)/secs));
    }

#if !__MSDOS__
/*
 * KAR-8/92, added to check the current level KCC is running on
 * and use the leveled header file directories. (PPS 4516)
 */

static
int
set_level (int level)
    {
    long    ac = level;
    long    ret_val;


    asm("\tSEARCH CSISYM\n");

    if (ICSIUUO_ACVAL("STLEV$", ac, ret_val))
	return (int) ret_val;
    else
	return STLEV_FAILURE;
    }
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -