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

📄 ccout.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
	    {
	    outstr ("\tEXTERN\t");
	    outstr (crtsnam[i]);
	    outnl ();
	    }
	}

    outdecl ();			/* Output user-defined INTERN and EXTERNs */

    /* Finally, output entry vector if any */

    makprefile ();	/* KAR-2/92, added to output entry pts in .MAC file */

    if (module_pragma)
	outstr ("\tPRGEND");
    else
	outstr ("\tEND");

    if (mainf)
	outstr ("\t<3,,$$STRT>");	/* 3 wds in entry vector */

    outnl ();
    outnl ();
}

/* OUTDECL - Output assembler external & internal declarations at end
**	of compiling a module (translation unit).
*/
static int
outdecl (void)
{
    SYMBOL *s = symbol;		/* Start of global sym list */
    int num = 0;

    while ((s = s->Snext) != NULL)
	{
	switch (s->Sclass)
	    {
	    default:
		continue;

	    case SC_EXTDEF:		/* External linkage sym defined */
		continue;

	    case SC_EXTREF:		/* External linkage sym referenced */
	    case SC_XEXTREF:
	    /* Symbol not defined.  Ask for it if needed */
		if (s->Srefs == 0)	/* If never used, don't ask. */
		    {
		    if (!delete)		/* If keeping asm file, */
			outc (';');		/* output it as a comment. */
		    else
			continue;		/* Otherwise just ignore */
		    }
		outstr ("\tEXTERN\t");
		break;
	    }
	outmiref (s);
	outnl ();
	}
    return num;
}

/* MAKPREFILE - determines whether a prefix assembler file is needed
**	and creates it if so.  Returns non-zero if one was created.
*/
int
makprefile (void)
{
    SYMBOL *sym;

    int nexfs = 0;

    /* Scan symbol table to see if there are any names
    ** we should export as library entry points.
    */

    for (sym = symbol; (sym = sym->Snext) != NULL;)
	if (sym->Sclass == SC_EXTDEF)	/* An external definition? */
	    break;				/* Yup */

    if (sym == NULL)
	return 0;	/* If none, just return */

    /* OK, now output entry statements for the exportable symbols */
    do
	{
	if (sym->Sclass == SC_EXTDEF)	/* For each external def */
	    {
	    if ((nexfs % 5) == 0)
		outstr ("\n\tENTRY ");
	    else
		outc (',');
	    outmiref (sym);
	    ++nexfs;
	    }
	sym = sym->Snext;
	}
    while (sym)
	;

    outnl ();

    return (nexfs);
}

/*
** KCC Assembler Header output
**
** This section contains the code required to generate the assembler header
** text that KCC puts at the beginning of all its assembler
** output files, just after any ENTRY or TITLE statements, and before
** any generated code.
**
** The header for both FAIL and MACRO is identical.
** However, MIDAS requires a somewhat different syntax.
*/

/* OUTASMH -  Output assembler header file.
**
** Copy Assembler Header File from its default or user-specified location.
** This should end up in the code segment, and supply macros
** %%CODE and %%DATA for switching between the two.
*/

static
char*	    asmhdr = NULL;

static
void
outasmh (void)
    {
    FILE*	hdrf;
    register
    int		c;


    /* If user explicitly specified an assembler header file, use it. */

    if (asmhfile)
	{
	if ((hdrf = fopen (asmhfile, "r")) == NULL) /* open file */
	    errfopen ("preamble", asmhfile);	/* no luck, give up */
	else
	    {
	    while ((c = getc (hdrf)) != EOF)
		outc (c); /* copy file */

	    if (ferror (hdrf) || !feof (hdrf))
		jerr ("I/O error while reading preamble \"%s\"", asmhfile);

	    fclose (hdrf);
	    return;
	    }
	}

    /* No file specified, or couldn't open.  Use self-generated header. */
    outstr (asmhdr ? asmhdr : ahmacs ());	/* Make or use existing */
    }

/* Segmentation macros.  See codeseg () and dataseg () for more comments. */

static char segfai[] = "\
	DEFINE %%CODE <RELOC>\n\
	DEFINE %%DATA <RELOC>\n\n\
	TWOSEG	400000	\n\
	RELOC	0	\n\
	RELOC	400000	\n";

static char segkdb[] = "\
	DEFINE %%CODE <RELOC>\n\
	DEFINE %%DATA <RELOC>\n\n\
	EXTERN	KD$DLD	\n\
	TWOSEG	400000	\n\
	LOC	041	\n\
	PUSHJ	17,KD$DLD\n\
	RELOC	0	\n\
	RELOC	400000	\n";

static char segfnp[] = "\
	DEFINE %%CODE <RELOC>\n\
	DEFINE %%DATA <RELOC>\n\n\
	EXTERN	KD$FPL	\n\
	TWOSEG	400000	\n\
	LOC	041	\n\
	PUSHJ	17,KD$FPL\n\
	RELOC	0	\n\
	RELOC	400000	\n";

static char segsp[] = "\
	DEFINE %%CODE <RELOC>\n\
	DEFINE %%DATA <RELOC>\n\n\
	EXTERN	KD$SPL	\n\
	TWOSEG	400000	\n\
	LOC	041	\n\
	PUSHJ	17,KD$SPL\n\
	RELOC	0	\n\
	RELOC	400000	\n";

static char *
ahmacs (void)
{
    register char *cp;
    char *beg;
    int size;

    /* To construct the possibly large header string, we steal space
    ** by re-using the pcode buffer temporarily.  Check when done to ensure
    ** it wasn't overflowed!
    */
    beg = cp = (char *)codes;

    if (profbliss)			/* profiling switch for CSI */
	cp = estrcpy (cp, "\t.REQUIRE BLI:PROFIL.REL\n");
    /*
     * KAR-1/92, advent of library version of KCCDBG.REL caused this code to
     * be changed so that any value of debcsi requests KCCDBG.REL.
     * I removed the #if __MSDOS__ because the code needs to always execute.
     */
    else
	switch (abs (debcsi))		/* debugging switch for CSI */
	    {
	    case 0 :
		break;

	    case KCC_DBG_SDBG :
	    case KCC_DBG_FDBG :		    /* FW 2A (42) PPS4575 */
	    case KCC_DBG_SPRF :
	    case KCC_DBG_FPRF :
	    case KCC_DBG_NULL :
		cp = estrcpy (cp, "\t.REQUEST SYS:KCCDBG.REL\n");
		break;


	    default:
		int_error ("ahmacs: invalid debcsi %d", debcsi);
	    }

    /*
     * Make request for standard C library.
     * Eventually flush this request and rely on KCC linker invocation.
     */

    cp = estrcpy (fstrcpy (estrcpy (cp, "\t.REQUEST "), libpath, "c"), "\n");

    sprintf (cp,"\t$$CVER==:<%o,,%o>\n",
	    cvercode, cverlib);

    cp += strlen (cp);			/* Sigh, update ptr */

    /* Add machine-dependent macro definitions */

    if (profbliss)			    /* added 09/15/89 by MVS */
	cp = estrcpy (cp, "\tOPDEF\tPROF. [37B8]\n");

    if (debcsi)				    /* source debugger UUO's */
	{
	cp = estrcpy (cp, "\tOPDEF\tDEBUGP [37B8]\n");
	cp = estrcpy (cp, "\tOPDEF\tDEBUGS [37B8]\n");
	cp = estrcpy (cp, "\tOPDEF\tDEBUGE [37B8]\n");
	}

    /*
     * Try to purge MACRO pseudo-ops that we'll never need and that
     * may conflict with user-defined syms.
     */

    cp = estrcpy (cp, "\
PURGE IFE,IFN,IFG,IFGE,IFL,IFLE,IFDEF,IFNDEF,IFIDN,IFDIF\n\n");

    /* Code and data segmentation setup and %%DATA/%%CODE macro definition */

    switch (debcsi)
	{
	case 0 :			/* no debugger or profiler */
	default :
	    cp = estrcpy (cp, segfai);
	    break;


	case KCC_DBG_SDBG :		/* source-level debugger */
	case KCC_DBG_FDBG :		    /* FW 2A (42) PPS4575 */
	    cp = estrcpy (cp, segkdb);
	    break;


	case KCC_DBG_SPRF :		/* statement profiler */
	    cp = estrcpy (cp, segsp);
	    break;


	case KCC_DBG_FPRF :		/* function profiler */
	    cp = estrcpy (cp, segfnp);
	    break;
	}

    if (mlist)
	cp = estrcpy (cp, "\n\tSP=17");

    if ((!delete) || mlist)
	cp = estrcpy (cp, "\n;\t*** User code begins here ***\n");

    size = strlen (beg) + 1;		/* Find size of entire header */

    if (size > sizeof (codes))		/* Paranoia check */
	fatal ("Assembler header table overflow");

    if ((asmhdr = calloc (1, size)) != NULL)  /* Now try to relocate it */
	{
	strcpy (asmhdr, beg);		/* Won, copy header to save it! */
	return asmhdr;
	}

    return beg;			/* No luck, just re-generate each time */
}

static char *
ahmacdef (char *cp, char **macro)
{
    cp = estrcpy (estrcpy (estrcpy (cp,"\tDEFINE "),macro[0]),
	    " (A,M)\n\t<");

    while (*++macro)
	cp = estrcpy (estrcpy (estrcpy (cp, "\t"), *macro), "\n");

    cp = estrcpy (cp, "\t>\n");

    return cp;
}

/*
** Data segmentation.
**
** KCC emits code in two sections: code and data.  The header sets things up
** so that code and data are in the high and low segments, which typically
** correspond to the high and low halves of their section but which can be
** rearranged by the appropriate LINK directives.
**
** Code and data are separated in the assembly output by the %%CODE and %%DATA
** macros.  %%CODE will never be called from any context other than the data
** segment, and vice versa.  KCC expects the header to initially be in code.
**
** During code generation, codeseg () and dataseg () are used to switch
** between the two segments.
*/

/* CODESEG - Start using code (pure) segment
*/
int
codeseg (void)
{
    int oseg;
    if ((oseg = whichseg) < 0)	/* if in data */
	{
	outstr ("\n\t%%CODE\n");		/* put in code instead */
#if SYS_CSI
	if (mlist)
	    oline += 2;
#endif
	whichseg = 1;			/* and remember in code */
	}
    return oseg;
}

/* DATASEG - Start using data (impure) segment
*/
int
dataseg (void)
{
    int oseg;
    if ((oseg = whichseg) > 0)	/* if in code */
	{
	outstr ("\n\t%%DATA\n");		/* put in data instead */
#if SYS_CSI
	if (mlist)
	    oline += 2;
#endif
	whichseg = -1;			/* and remember in data */
	}
    return oseg;
}

/* PREVSEG - restore to previous segment
*/
int
prevseg (int seg)
{
    return (seg < 0) ? dataseg () : codeseg ();
}

/* REALCODE (p) - Generate real code for given pseudo-instruction.
**	This is the primary assembler output function.
*/
void
realcode (PCODE *p)
{
    int i, typ;

    typ = (p->Ptype &~ PTF_SKIPPED);	/* Get sanitized addressing type */

    switch (p->Pop & POF_OPCODE)
	{

	case P_NOP:			/* Ignore deleted pseudo-code */
	    return;

    /* Handle the various simulated ops, which do not correspond
    ** directly to a real PDP-10 instruction.
    */
	case P_PTRCNV:
	    simptrcnv (p);
	    return;	/* "Pointer Conversion"  */
	case P_SMOVE:
	    simsmove (p);
	    return;	/* "Structure Move" */
	case P_UFLTR:
	    simufltr (p);
	    return;	/* "Unsigned Float & Round" */
	case P_UIDIV:
	    simuidiv (p);
	    return;	/* "Unsigned Integer Divide" */
	case P_SUBBP:
	    simsubbp (p);
	    return;	/* "Subtract Byte Pointer" */
	case P_DFIX:
	    simdfix (p);
	    return;	/* "Double Fix" */
	case P_DSNGL:
	    simdsngl (p);
	    return;	/* "Double to Single" */

    /* End of simulated ops; switch continued on next page! */
	    
    /* Switch continued from previous page!  Start of "real" ops. */

    /*
    ** If we are doing a test or comparison with a number, and the number
    ** is larger than 18 bits, we have to use a literal.
    ** We also have to perform a similar transformation if we want
    ** to compare the register with an immediate address.
    ** This entails changing the opcode from TRN to TDN, CAI to CAM, etc.
    ** Note this is NOT an optimization -- it is needed to avoid generating
    ** impossible instructions.
    */
	case P_TRN:
	    if (foldtrna (p))
		return;
	case P_TRC:

⌨️ 快捷键说明

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