📄 stfe.c
字号:
/* --------------------------------------------------------- *//* | Copyright (c) 1986, 1989 MIPS Computer Systems, Inc. | *//* | All Rights Reserved. | *//* --------------------------------------------------------- *//* $Header: stfe.c,v 2010.2.1.3 89/11/29 14:28:44 bettina Exp $ *//* * Author Mark I. Himelstein * Date started 5/10/85 * Module stfe.c * Purpose provide a set of routine to interface to front-ends, which * will be used to build up the symbol table. These routines * are really second level and combine the basic routines * to provide higher level functions. * * Naming conventions: * - all function interfaces are prefixed with st_ * - functions returning a value from an arg have names of the * form result_arg * - all globals prefixed with a st_ * - all arrays start with an a * - all pointers start with a p * - an array mapping thing1 to thing to is named mthing1_thing2 */#include "syms.h"#include "stext.h"#include "cmplrs/usys.h"#include "cmplrs/ucode.h"#define ST_NESTMAX 20static DNR *adn_stack; /* stack of begin blocks */static long idn_stack; /* counter for the stack */static long dn_stackmax; /* counter for the stack */static DNR *filestack; /* stack of files */static long ifilestack; /* counter for stack of files */static long filestackmax; /* counter for max stack of files */export long st_filebegin (filename, lang, merge, glevel)char *filename;{ /* * This routine takes afilename and return a dense number for the * file. * If it didn't exist before, it is created and made the * current file and pushed on the file stack. * If it did exist, * and it is closed off with the appropriate stEnd local symbol * a new one is created as above. * If it did exist and is not closed off, * we need to find it on the filestack, we pop off and end all files * above the file we are looking for on the stack. * * Regardless we always return the dense number for the stFile symbol. */ long ifd; /* just search through the files. If we already have an entry * return it, otherwise return a new one. */ for (ifd = 0; ifd < st_ifdmax(); ifd++) { if (!strcmp(filename, st_str_ifd_iss (ifd, ST_FDISS))) { int i; /* if it's not in the current filestack, it's not it */ for (i = ifilestack - 1; i >= 0; i--) { if (ifd == filestack[i].rfd) break; } /* for */ if (i < 0) continue; while (ifd != filestack[ifilestack-1].rfd) { if (--ifilestack < 0) st_internal ("st_filebegin: tried to end too many files (%s)\n", filename); } /* while */ st_setfd (ifd); return (filestack[ifilestack-1].index); } /* if */ } /* for */ st_fdadd (filename, lang, merge, glevel); st_feinit(); /* add to the filestack which keeps track of CPP style line/file * announcements and figures out when to remove a file. */ if (ifilestack + 1 > filestackmax) filestack = (pDNR) st_malloc (filestack, &filestackmax, cbDNR, ST_FILESINIT); filestack[ifilestack].rfd = st_currentifd(); filestack[ifilestack].index = st_idn_index_fext (st_symadd(ST_FDISS, valueNil, stFile, scText, indexNil), 0); return (filestack[ifilestack++].index);}export void st_endallfiles(){ pSYMR psym; pCFDR pcfd; long ifd; long old_ifd; long temp; old_ifd = st_currentifd(); /* ends all files from the filestack */ for (ifd = 0; ifd < st_ifdmax(); ifd++) { pcfd = st_pcfd_ifd (ifd); if (pcfd->psym != symNil && pcfd->psym != (pSYMR)-1 && pcfd->pfd->csym > 0 && pcfd->psym[pcfd->pfd->csym-1].st == stEnd && pcfd->psym[pcfd->pfd->csym-1].index == 0) /* this file is closed */ continue; st_setfd (ifd); psym = st_psym_ifd_isym (ifd, 0); temp = st_symadd(psym->iss, valueNil, stEnd, scText, 0); psym = st_psym_ifd_isym (ifd, 0); psym->index = ++temp; } /* for */ st_setfd (old_ifd);} /* st_endallfiles */export long st_fileend (idn)long idn;{ /* we usually figure out we need to end a file after we've already * started another so this routine first sets up the file we're * ending as the current file, get the symbol for the beginning * of file and add's the end of file symbol. The indexes are updated * appropriately. */ DNR dn; pSYMR psym; pCFDR pcfd; long ifd; dn = *st_pdn_idn (idn); pcfd = st_pcfd_ifd (dn.rfd); if (pcfd->psym != symNil && pcfd->psym != (pSYMR)-1 && pcfd->pfd->csym > 0 && pcfd->psym[pcfd->pfd->csym-1].st == stEnd && pcfd->psym[pcfd->pfd->csym-1].index == 0) /* this file is closed */ return -1; ifd = st_currentifd(); st_setfd (dn.rfd); psym = st_psym_ifd_isym (dn.rfd, dn.index); dn.index = psym->index = st_symadd(psym->iss, valueNil, stEnd, scText, 0); psym->index++; st_setfd (ifd); return (st_idn_dn (dn));} /* st_fileend */static st_fblockpending = 0; /* set if we just got a nested text block *//* Algorithm for adding textblocks: * * when the begin block or left brace is encountered: * * idn = st_blockbegin (issNull, 0, scText); * if (idn != 0) * generate u-code begin block; * endif * * if the block contains local declarations then before the first one: * idn = st_textblock(); * if (idn != 0) * generate u-code begin block; * endif * * when an end of block is encountered: * idn = st_endblock(); * if (idn != 0) * generate u-code end block; * endif */export long st_textblock(){ /* this routine is used to begins nested language blocks. * if a block is oending we add the symbol and update the block stack. */ long index; DNR dn; if (st_fblockpending && idn_stack > 1) { st_fblockpending = 0; index = st_symadd (0, 0, stBlock, scText, 0); dn.rfd = st_currentifd(); dn.index = index; adn_stack [idn_stack - 1] = dn; return (st_idn_dn (dn)); } else if (st_fblockpending) { st_internal ("st_textblock: block pending set in illegal case\n"); } /* if */ return (0);} /* st_blockbegin */export long st_blockbegin(iss, value, sc)long iss;long value;long sc;{ /* this routine is used to begin structures/etc and language blocks. * we add the symbol and store an dn for it in the block stack. * we return a dense number referencing the begin block symbol. * If it's a nested textblock we only note the begin on the block * stack and a subsequent st_textblock will make the actual symbol. */ long index; DNR dn; if (sc == scText && idn_stack != 0) { st_fblockpending = 1; index = ST_ANONINDEX; } else { index = st_symadd (iss, value, stBlock, sc, 0); } /* if */ dn.rfd = st_currentifd(); dn.index = index; if (idn_stack + 1 > dn_stackmax) adn_stack = (pDNR) st_malloc (adn_stack, &dn_stackmax, cbDNR, ST_FILESINIT); adn_stack [idn_stack++] = dn; if (index == ST_ANONINDEX) return (0); return (st_idn_dn (dn));} /* st_blockbegin */export long st_blockend(size)long size;{ /* this routine is used to etc structures/etc and language blocks. * we get the corresponding begin block symbol, add the end block * symbol and fix the indexes. If it's scText we must emit the * end block ucode otherwise we must update the size in the * begin block for structures/etc cause we only know the size at * this point. * If it's a text block and a st_block symbol was never emitted then * a zero is returned. */ pSYMR psym; DNR dn; long index; long tempifd; dn = adn_stack [--idn_stack]; if (dn.index == ST_ANONINDEX) { st_fblockpending = 0; return (0); } /* if */ psym = st_psym_ifd_isym (dn.rfd, dn.index); tempifd = st_currentifd(); st_setfd(dn.rfd); index = st_symadd (issNull, valueNil, stEnd, psym->sc, adn_stack [idn_stack].index) + 1; /* need to refresh pointer, that may have been moved by symadd */ psym = st_psym_ifd_isym (dn.rfd, dn.index); psym->index = index; if (psym->sc != scText) /* it's a struct/etc. and we can only fill this in now */ psym->value = size; index = st_idn_index_fext (psym->index - 1, 0); st_setfd(tempifd); return (index);} /* st_blockend */export void st_blockpop (){ /* we decided to pop the block instead of making an end for it */ --idn_stack;} /* st_blockpop */export long st_procend(idn)long idn;{ /* the proc's block no. is the idn (our arg), which points to the * external symbol whose index points to the local symbol or
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -