output.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,471 行 · 第 1/3 页
C
1,471 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include "wic.h"
#include "output.h"
#include "outfort.h"
#include "outasm.h"
typedef struct {
PrintType type; // If type == LIST then the type is in 'list'.
void* data;
struct {
PrintType type;
pSLList list;
} list;
int fileNum; // MAIN_FILE for normal output (.fi for fortran, .inc for asm)
// SECONDARY_FILE for alternative output (.fap for fortran,
// none for asm)
void* param;
} PT_StackElem, *pPT_StackElem; // print type stack, used by output.c
static struct {
char fileName[MAX_NUM_OF_OUT_FILES][_MAX_PATH];
FILE *output[MAX_NUM_OF_OUT_FILES];
char lastChar[MAX_NUM_OF_OUT_FILES]; // Last char written
char line[MAX_NUM_OF_OUT_FILES][MAX_OUT_LINE_LEN];
char lineComment[MAX_OUT_LINE_LEN];
char lineLen[MAX_NUM_OF_OUT_FILES];
enum {
LF_NONE = 0x0,
LF_CONT = 0x1,
LF_NEED_CONT_SIG = 0x2, // Need continue signature at beginning of line
LF_DIRECTIVE = 0x4,
} lineFlags[MAX_NUM_OF_OUT_FILES];
} fileStack[MAX_INCLUDE_NEST];
#define LF_INIT_FORT_FLAGS LF_NONE
#define LF_INIT_ASM_FLAGS LF_NONE
#define PT_STACK_MAX 50
typedef struct {
pOUnit nextOUnit;
PT_StackElem stack[PT_STACK_MAX];
int stackPos;
} PrintInfo;
static pHTable keywordsTable = NULL;
static PrintInfo printData[NUM_OF_PRINT_TYPES];
static PrintStackType currWorkStack;
static pOUnit currOUnit;
static int linesLeftToSkip = 0;
static int fileStackLevel = -1;
#define CURR_OUTPUT(i) (fileStack[fileStackLevel].output[(i)])
#define CURR_FILE_NAME(i) (fileStack[fileStackLevel].fileName[(i)])
#define CURR_FILE_POS(i) (fileStack[fileStackLevel].filePos[(i)])
#define CURR_LAST_CHAR(i) (fileStack[fileStackLevel].lastChar[(i)])
#define CURR_LINE(i) (fileStack[fileStackLevel].line[(i)])
#define CURR_LINE_LEN(i) (fileStack[fileStackLevel].lineLen[(i)])
#define CURR_LINE_COMMENT (fileStack[fileStackLevel].lineComment)
#define CURR_LINE_FLAGS(i) (fileStack[fileStackLevel].lineFlags[(i)])
TargetLangOpt g_tlang;
static pOUnit _createOUnit(OUnitType type, pTokPos pos, char *string) {
pOUnit newUnit = wicMalloc(sizeof *newUnit);
newUnit->type = type;
if (pos != NULL) {
memcpy(&(newUnit->pos), pos, sizeof *pos);
newUnit->posPresent = 1;
} else {
newUnit->posPresent = 0;
}
newUnit->fileNum = MAIN_FILE;
newUnit->preStackLevel = 0;
newUnit->postStackLevel = 0;
if (string != NULL) {
strncpy(newUnit->string, string, MAX_TOKEN_SIZE);
} else {
newUnit->string[0] = 0;
}
newUnit->stringIsId = 0;
return newUnit;
}
pOUnit createOUnitText(char *string, pTokPos pos) {
pOUnit newUnit = _createOUnit(OUT_TEXT, pos, string);
return newUnit;
}
pOUnit createOUnitTextId(char *string, pTokPos pos) {
pOUnit newUnit = createOUnitText(string, pos);
newUnit->stringIsId = 1;
return newUnit;
}
pOUnit createOUnitNewline(void) {
pOUnit newUnit = _createOUnit(OUT_NEWLINE, NULL, NULL);
return newUnit;
}
pOUnit createOUnitFromTok(pToken tok) {
pOUnit newUnit;
int code;
if (tok == NULL) {
return NULL;
}
code = tok->data->code;
if (code == Y_EOF) {
newUnit = _createOUnit(OUT_EOF, tok->pos, NULL);
} else {
OUnitType newType = OUT_TEXT;
if (code == Y_PRE_COMMENT) {
newType = OUT_COMMENT;
}
newUnit = _createOUnit(newType, tok->pos, NULL);
getTokDataStr(tok->data, 1, newUnit->string, MAX_TOKEN_SIZE);
newUnit->stringIsId = (code == Y_ID);
}
return newUnit;
}
pOUnit addOUnitPrefix(pOUnit unit, char *preString) {
if (unit->preStackLevel >= _OUNIT_STR_STACK_MAX) {
reportError(ERR_INTERNAL_STACK_OVERFLOW);
} else {
unit->preStrStack[unit->preStackLevel++] = preString;
}
return unit;
}
pOUnit addOUnitPostfix(pOUnit unit, char *postString) {
if (unit->postStackLevel >= _OUNIT_STR_STACK_MAX) {
reportError(ERR_INTERNAL_STACK_OVERFLOW);
} else {
unit->postStrStack[unit->postStackLevel++] = postString;
}
return unit;
}
pOUnit addOUnitPrePost(pOUnit unit, char *preString, char* postString) {
return addOUnitPostfix( addOUnitPrefix( unit, preString ), postString );
}
void zapOUnit(pOUnit unit) {
wicFree(unit);
}
pOUnit addOUnitPostfixImmediate(pOUnit unit, char *postString) {
int len;
char *s;
if (unit == NULL || postString == NULL) {
return unit;
}
s = unit->string;
len = strlen(s);
strncpy(s+len, postString, max(0, MAX_TOKEN_SIZE - len - 1));
return unit;
}
pOUnit createOUnitDclrName(char *name, pTokPos typePos, char *postfix) {
char *middle = g_opt.structFieldsSep;
if (postfix == NULL) {
middle = NULL;
}
if (!g_opt.prefixStructFields) {
postfix = NULL;
}
return addOUnitPostfixImmediate(
addOUnitPostfixImmediate(
createOUnitTextId(name, typePos),
middle
),
postfix
);
}
/*--------------------------------------------------------------------------*/
static void fprintfCheckNULL(FILE *fp, const char *format, ...) {
if (fp != NULL) {
va_list arglist;
va_start(arglist, format);
vfprintf(fp, format, arglist);
va_end(arglist);
}
}
void _outputCurrAsmLine(int fnum, int continueToNextLine) {
char *line = CURR_LINE(fnum);
FILE *output = CURR_OUTPUT(fnum);
int len = CURR_LINE_LEN(fnum);
int flags = CURR_LINE_FLAGS(fnum);
#ifndef NDEBUG
if (g_opt.debug) {
output = stdout;
}
#endif
fprintfCheckNULL(output, "%.*s", len, line);
if (continueToNextLine) {
if (len > 0) {
fprintfCheckNULL(output, "\\");
flags |= LF_CONT;
} else {
if (flags & LF_CONT) {
fprintfCheckNULL(output, "\\");
}
}
}
if (fnum == MAIN_FILE) {
fprintfCheckNULL(output, "%s", CURR_LINE_COMMENT);
}
fprintfCheckNULL(output, "\n");
/* Printing done, initialize next line */
if (!continueToNextLine) {
flags &= ~LF_CONT;
}
CURR_LINE_FLAGS(fnum) = flags;
CURR_LINE_LEN(fnum) = 0;
if (fnum == MAIN_FILE) {
CURR_LINE_COMMENT[0] = 0;
}
CURR_LAST_CHAR(fnum) = '\n';
}
void _outputCurrFortLine(int fnum, int continueToNextLine) {
char *line = CURR_LINE(fnum);
int len = CURR_LINE_LEN(fnum);
FILE *output = CURR_OUTPUT(fnum);
int flags = CURR_LINE_FLAGS(fnum);
char *prependString = " ";
int spacesBegLine = 0;
char *leftOver = NULL;
int leftOverLen = 0;
assert(fileStackLevel >= 0);
#ifndef NDEBUG
if (g_opt.debug) {
output = stdout;
}
#endif
/* Get rid of spaces */
for (; line[0] == '\t' && len > 0;) {
line += 1;
len -= 1;
spacesBegLine += TAB_SIZE;
}
while (line[0] == ' ' && len > 0) {
for (; line[0] == ' ' && len > 0;) {
line++;
len--;
spacesBegLine += 1;
}
for (; line[0] == '\t' && len > 0;) {
line += 1;
len -= 1;
spacesBegLine += TAB_SIZE;
}
}
for (; line[0] == ' ' && len > 0;) {
line++;
len--;
spacesBegLine += 1;
}
if (!(flags & LF_CONT) || !(flags & LF_NEED_CONT_SIG)) {
if (len > 1 && line[0] == '*' && line[1] == '$') { // Is a directive
prependString = "";
spacesBegLine = 0;
flags |= LF_DIRECTIVE;
}
}
if (flags & LF_DIRECTIVE || len == 0) {
if (flags & LF_NEED_CONT_SIG) {
prependString = "*";
} else {
spacesBegLine = 0;
prependString = "";
}
} else {
if (flags & LF_CONT && flags & LF_NEED_CONT_SIG) {
prependString = " &";
}
}
fprintfCheckNULL(output, "%s", prependString);
fprintfCheckNULL(output, "%*s", spacesBegLine, "");
if (continueToNextLine) {
int i = len-1;
int class1, class2;
if (! (flags & LF_DIRECTIVE)) {
i -= 6; // Take into account the 6 spaces at the beginning of line
}
while (i > 1) {
class2 = isalnum(line[i]);
class1 = isalnum(line[i-1]);
if ((class1 == 0) || (class2 == 0) || (class1 != class2)) {
// found a place to split!
leftOverLen = len - i;
len = i;
leftOver = line+len;
break;
}
i--;
}
}
fprintfCheckNULL(output, "%.*s", len, line);
if (continueToNextLine && flags & LF_DIRECTIVE) {
fprintfCheckNULL(output, "\\");
}
if (fnum == MAIN_FILE && CURR_LINE_COMMENT[0] != 0) {
char *s = CURR_LINE_COMMENT;
int i = 0;
while(s[0] == ' ') {
i++; s++;
}
if (i == 5 && len == 0) {
i++; // Avoid having '!' in sixth column
}
fprintfCheckNULL(output, "%*.s%s", i, "", s);
}
fprintfCheckNULL(output, "\n");
/* Printing done, initialize next line */
if (continueToNextLine) {
flags |= LF_CONT;
if (len != 0) {
flags |= LF_NEED_CONT_SIG;
}
} else {
flags = g_tlang.lfInitFlags;
}
CURR_LINE_FLAGS(fnum) = flags;
if (leftOver != NULL) {
CURR_LINE_LEN(fnum) = leftOverLen;
memcpy(CURR_LINE(fnum), leftOver, CURR_LINE_LEN(fnum));
} else {
CURR_LINE_LEN(fnum) = 0;
}
if (fnum == MAIN_FILE) {
CURR_LINE_COMMENT[0] = 0;
}
CURR_LAST_CHAR(fnum) = '\n';
}
static void _outputChar(int fnum, char ch) {
int substract = g_tlang.substractFromLineLen;
if (CURR_LINE_LEN(fnum) >= g_opt.outLineLen-substract) {
g_tlang.outputCurrLine(fnum, 1);
}
CURR_LINE(fnum)[CURR_LINE_LEN(fnum)++] = ch;
if (ch == '\n') {
assert(0);
g_tlang.outputCurrLine(fnum, 0);
CURR_LAST_CHAR(fnum) = ch;
} else if (isspace(ch)) {
CURR_LAST_CHAR(fnum) = ch;
}
}
static void _outputString(int fnum, char *s, int stringIsId) {
char lastChar;
int i;
if (s == NULL) {
return;
}
assert(0 <= fnum && fnum < g_tlang.numOfOutFiles);
if (s[0] == 0) {
return;
}
lastChar = s[strlen(s)-1];
if ((isalnum(CURR_LAST_CHAR(fnum)) || CURR_LAST_CHAR(fnum) == '_') &&
(isalnum(lastChar) || lastChar == '_') ) {
_outputChar(fnum, ' ');
}
if (stringIsId) {
if (findHTableElem(keywordsTable, s) != NULL) {
char *s;
for (s = g_opt.conflictPrefix; *s != 0; s++) {
_outputChar(fnum, *s);
}
}
}
for (i = 0; s[i] != NULL; i++) {
_outputChar(fnum, s[i]);
}
CURR_LAST_CHAR(fnum) = lastChar;
}
void _outputContinueLine(fileNum) {
g_tlang.outputCurrLine(fileNum, 1);
}
void _outputOUnit(pOUnit unit) {
int spacesBefore = unit->pos.spacesBefore;
int commentSize, commentLeft;
int i;
assert(unit->posPresent);
if (unit->type == OUT_TEXT) {
for (; spacesBefore > 0; spacesBefore --) {
_outputChar(unit->fileNum, ' ');
}
} else if (unit->type == OUT_COMMENT) {
commentSize = strlen(CURR_LINE_COMMENT);
commentLeft = sizeof CURR_LINE_COMMENT - commentSize-1;
for (; spacesBefore > 0 && commentLeft > 0;
spacesBefore--, commentLeft--)
{
CURR_LINE_COMMENT[commentSize++] = ' ';
}
CURR_LINE_COMMENT[commentSize] = 0;
}
for (i = unit->preStackLevel-1; i >= 0; i--) {
_outputString(unit->fileNum, unit->preStrStack[i], 0);
}
switch (unit->type) {
case OUT_TEXT:
_outputString(unit->fileNum, unit->string, unit->stringIsId);
break;
case OUT_NEWLINE:
g_tlang.outputCurrLine(unit->fileNum, 0);
break;
case OUT_COMMENT:
strncpy(CURR_LINE_COMMENT+commentSize, unit->string, commentLeft);
break;
case OUT_EOF:
break;
}
for (i = unit->postStackLevel-1; i >= 0; i--) {
_outputString(unit->fileNum, unit->postStrStack[i], 0);
}
}
void _popFileStack(void) {
int i;
assert(fileStackLevel >= 0);
for (i = 0; i < g_tlang.numOfOutFiles; i++) {
g_tlang.outputCurrLine(i, 0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?