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 + -
显示快捷键?