alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (SDE.c)

This example Java source code file (SDE.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

eof, exit_error, filetablerecord, init_size_file, init_size_line, init_size_stratum, java, linetablerecord, null, nullstring, sde, sourcemap, stratumtablerecord, string

The SDE.c Java example source code

/*
 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include <setjmp.h>

#include "util.h"
#include "SDE.h"

#ifdef __APPLE__
/* use setjmp/longjmp versions that do not save/restore the signal mask */
#define setjmp _setjmp
#define longjmp _longjmp
#endif

/**
 * This SourceDebugExtension code does not
 * allow concurrent translation - due to caching method.
 * A separate thread setting the default stratum ID
 * is, however, fine.
 */

#define INIT_SIZE_FILE 10
#define INIT_SIZE_LINE 100
#define INIT_SIZE_STRATUM 3

#define BASE_STRATUM_NAME "Java"

#define null NULL
#define true JNI_TRUE
#define false JNI_FALSE
#define String char *
#define private static

typedef struct {
  int fileId;
  String sourceName;
  String sourcePath; // do not read - use accessor
  int isConverted;
} FileTableRecord;

typedef struct {
    int jplsStart;
    int jplsEnd;
    int jplsLineInc;
    int njplsStart;
    int njplsEnd;
    int fileId;
} LineTableRecord;

typedef struct {
    String id;
    int fileIndex;
    int lineIndex;
} StratumTableRecord;

/* back-end wide value for default stratum */
private String globalDefaultStratumId = null;

/* reference type default */
private String defaultStratumId = null;

private jclass cachedClass = NULL;

private FileTableRecord* fileTable;
private LineTableRecord* lineTable;
private StratumTableRecord* stratumTable;

private int fileTableSize;
private int lineTableSize;
private int stratumTableSize;

private int fileIndex;
private int lineIndex;
private int stratumIndex = 0;
private int currentFileId;

private int defaultStratumIndex;
private int baseStratumIndex;
private char* sdePos;

private char* jplsFilename = null;
private char* NullString = null;

/* mangled in parse, cannot be parsed.  Must be kept. */
private String sourceDebugExtension;

private jboolean sourceMapIsValid;

private jmp_buf jmp_buf_env;

private int stratumTableIndex(String stratumId);
private int stiLineTableIndex(int sti, int jplsLine);
private int stiLineNumber(int sti, int lti, int jplsLine);
private void decode(void);
private void ignoreWhite(void);
private jboolean isValid(void);

    private void
    loadDebugInfo(JNIEnv *env, jclass clazz) {

        if (!isSameObject(env, clazz, cachedClass)) {
            /* Not the same - swap out the info */

            /* Delete existing info */
            if ( cachedClass != null ) {
                tossGlobalRef(env, &cachedClass);
                cachedClass = null;
            }
            if ( sourceDebugExtension!=null ) {
                jvmtiDeallocate(sourceDebugExtension);
            }
            sourceDebugExtension = null;

            /* Init info */
            lineTable = null;
            fileTable = null;
            stratumTable = null;
            lineTableSize = 0;
            fileTableSize = 0;
            stratumTableSize = 0;
            fileIndex = 0;
            lineIndex = 0;
            stratumIndex = 0;
            currentFileId = 0;
            defaultStratumId = null;
            defaultStratumIndex = -1;
            baseStratumIndex = -2; /* so as not to match -1 above */
            sourceMapIsValid = false;

            if (getSourceDebugExtension(clazz, &sourceDebugExtension) ==
                JVMTI_ERROR_NONE) {
                sdePos = sourceDebugExtension;
                if (setjmp(jmp_buf_env) == 0) {
                    /* this is the initial (non-error) case, do parse */
                    decode();
                }
            }

            cachedClass = null;
            saveGlobalRef(env, clazz, &cachedClass);
        }
    }

    /* Return 1 if match, 0 if no match */
    private int
    patternMatch(char *classname, const char *pattern) {
        int pattLen;
        int compLen;
        char *start;
        int offset;

        if (pattern == NULL || classname == NULL) {
            return 0;
        }
        pattLen = (int)strlen(pattern);

        if ((pattern[0] != '*') && (pattern[pattLen-1] != '*')) {
            return strcmp(pattern, classname) == 0;
        }

        compLen = pattLen - 1;
        offset = (int)strlen(classname) - compLen;
        if (offset < 0) {
            return 0;
        }
        if (pattern[0] == '*') {
            pattern++;
            start = classname + offset;
        }  else {
            start = classname;
        }
        return strncmp(pattern, start, compLen) == 0;
    }

    /**
     * Return 1 if p1 is a SourceName for stratum sti,
     * else, return 0.
     */
    private int
    searchOneSourceName(int sti, char *p1) {
        int fileIndexStart = stratumTable[sti].fileIndex;
        /* one past end */
        int fileIndexEnd = stratumTable[sti+1].fileIndex;
        int ii;
        for (ii = fileIndexStart; ii < fileIndexEnd; ++ii) {
            if (patternMatch(fileTable[ii].sourceName, p1)) {
              return 1;
            }
        }
        return 0;
    }

    /**
     * Return 1 if p1 is a SourceName for any stratum
     * else, return 0.
     */
    int searchAllSourceNames(JNIEnv *env,
                             jclass clazz,
                             char *p1) {
        int ii;
        loadDebugInfo(env, clazz);
        if (!isValid()) {
          return 0; /* no SDE or not SourceMap */
        }

        for (ii = 0; ii < stratumIndex - 1; ++ii) {
            if (searchOneSourceName(ii, p1) == 1) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * Convert a line number table, as returned by the JVMTI
     * function GetLineNumberTable, to one for another stratum.
     * Conversion is by overwrite.
     * Actual line numbers are not returned - just a unique
     * number (file ID in top 16 bits, line number in
     * bottom 16 bits) - this is all stepping needs.
     */
    void
    convertLineNumberTable(JNIEnv *env, jclass clazz,
                           jint *entryCountPtr,
                           jvmtiLineNumberEntry **tablePtr) {
        jvmtiLineNumberEntry *fromEntry = *tablePtr;
        jvmtiLineNumberEntry *toEntry = *tablePtr;
        int cnt = *entryCountPtr;
        int lastLn = 0;
        int sti;

        loadDebugInfo(env, clazz);
        if (!isValid()) {
            return; /* no SDE or not SourceMap - return unchanged */
        }
        sti = stratumTableIndex(globalDefaultStratumId);
        if (sti == baseStratumIndex) {
            return; /* Java stratum - return unchanged */
        }
        LOG_MISC(("SDE is re-ordering the line table"));
        for (; cnt-->0; ++fromEntry) {
            int jplsLine = fromEntry->line_number;
            int lti = stiLineTableIndex(sti, jplsLine);
            if (lti >= 0) {
                int fileId = lineTable[lti].fileId;
                int ln = stiLineNumber(sti, lti, jplsLine);
                ln += (fileId << 16); /* create line hash */
                if (ln != lastLn) {
                    lastLn = ln;
                    toEntry->start_location = fromEntry->start_location;
                    toEntry->line_number = ln;
                    ++toEntry;
                }
            }
        }
        /*LINTED*/
        *entryCountPtr = (int)(toEntry - *tablePtr);
    }

    /**
     * Set back-end wide default stratum ID .
     */
    void
    setGlobalStratumId(char *id) {
        globalDefaultStratumId = id;
    }


    private void syntax(String msg) {
        char buf[200];
        (void)snprintf(buf, sizeof(buf),
                "bad SourceDebugExtension syntax - position %d - %s\n",
                /*LINTED*/
                (int)(sdePos-sourceDebugExtension),
                msg);
        JDI_ASSERT_FAILED(buf);

        longjmp(jmp_buf_env, 1);  /* abort parse */
    }

    private char sdePeek(void) {
        if (*sdePos == 0) {
            syntax("unexpected EOF");
        }
        return *sdePos;
    }

    private char sdeRead(void) {
        if (*sdePos == 0) {
            syntax("unexpected EOF");
        }
        return *sdePos++;
    }

    private void sdeAdvance(void) {
        sdePos++;
    }

    private void assureLineTableSize(void) {
        if (lineIndex >= lineTableSize) {
            size_t allocSize;
            LineTableRecord* new_lineTable;
            int new_lineTableSize;

            new_lineTableSize = lineTableSize == 0?
                                  INIT_SIZE_LINE :
                                  lineTableSize * 2;
            allocSize = new_lineTableSize * (int)sizeof(LineTableRecord);
            new_lineTable = jvmtiAllocate((jint)allocSize);
            if ( new_lineTable == NULL ) {
                EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE line table");
            }
            if ( lineTable!=NULL ) {
                (void)memcpy(new_lineTable, lineTable,
                        lineTableSize * (int)sizeof(LineTableRecord));
                jvmtiDeallocate(lineTable);
            }
            lineTable     = new_lineTable;
            lineTableSize = new_lineTableSize;
        }
    }

    private void assureFileTableSize(void) {
        if (fileIndex >= fileTableSize) {
            size_t allocSize;
            FileTableRecord* new_fileTable;
            int new_fileTableSize;

            new_fileTableSize = fileTableSize == 0?
                                  INIT_SIZE_FILE :
                                  fileTableSize * 2;
            allocSize = new_fileTableSize * (int)sizeof(FileTableRecord);
            new_fileTable = jvmtiAllocate((jint)allocSize);
            if ( new_fileTable == NULL ) {
                EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE file table");
            }
            if ( fileTable!=NULL ) {
                (void)memcpy(new_fileTable, fileTable,
                        fileTableSize * (int)sizeof(FileTableRecord));
                jvmtiDeallocate(fileTable);
            }
            fileTable     = new_fileTable;
            fileTableSize = new_fileTableSize;
        }
    }

    private void assureStratumTableSize(void) {
        if (stratumIndex >= stratumTableSize) {
            size_t allocSize;
            StratumTableRecord* new_stratumTable;
            int new_stratumTableSize;

            new_stratumTableSize = stratumTableSize == 0?
                                  INIT_SIZE_STRATUM :
                                  stratumTableSize * 2;
            allocSize = new_stratumTableSize * (int)sizeof(StratumTableRecord);
            new_stratumTable = jvmtiAllocate((jint)allocSize);
            if ( new_stratumTable == NULL ) {
                EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY, "SDE stratum table");
            }
            if ( stratumTable!=NULL ) {
                (void)memcpy(new_stratumTable, stratumTable,
                        stratumTableSize * (int)sizeof(StratumTableRecord));
                jvmtiDeallocate(stratumTable);
            }
            stratumTable     = new_stratumTable;
            stratumTableSize = new_stratumTableSize;
        }
    }

    private String readLine(void) {
        char *initialPos;
        char ch;

        ignoreWhite();
        initialPos = sdePos;
        while (((ch = *sdePos) != '\n') && (ch != '\r')) {
            if (ch == 0) {
                syntax("unexpected EOF");
            }
            ++sdePos;
        }
        *sdePos++ = 0; /* null terminate string - mangles SDE */

        /* check for CR LF */
        if ((ch == '\r') && (*sdePos == '\n')) {
            ++sdePos;
        }
        ignoreWhite(); /* leading white */
        return initialPos;
    }

    private int defaultStratumTableIndex(void) {
        if ((defaultStratumIndex == -1) && (defaultStratumId != null)) {
            defaultStratumIndex =
                stratumTableIndex(defaultStratumId);
        }
        return defaultStratumIndex;
    }

    private int stratumTableIndex(String stratumId) {
        int i;

        if (stratumId == null) {
            return defaultStratumTableIndex();
        }
        for (i = 0; i < (stratumIndex-1); ++i) {
            if (strcmp(stratumTable[i].id, stratumId) == 0) {
                return i;
            }
        }
        return defaultStratumTableIndex();
    }


/*****************************
 * below functions/methods are written to compile under either Java or C
 *
 * Needed support functions:
 *   sdePeek()
 *   sdeRead()
 *   sdeAdvance()
 *   readLine()
 *   assureLineTableSize()
 *   assureFileTableSize()
 *   assureStratumTableSize()
 *   syntax(String)
 *
 *   stratumTableIndex(String)
 *
 * Needed support variables:
 *   lineTable
 *   lineIndex
 *   fileTable
 *   fileIndex
 *   currentFileId
 *
 * Needed types:
 *   String
 *
 * Needed constants:
 *   NullString
 */

    private void ignoreWhite(void) {
        char ch;

        while (((ch = sdePeek()) == ' ') || (ch == '\t')) {
            sdeAdvance();
        }
    }

    private void ignoreLine(void) {
        char ch;

        do {
           ch = sdeRead();
        } while ((ch != '\n') && (ch != '\r'));

        /* check for CR LF */
        if ((ch == '\r') && (sdePeek() == '\n')) {
            sdeAdvance();
        }
        ignoreWhite(); /* leading white */
    }

    private int readNumber(void) {
        int value = 0;
        char ch;

        ignoreWhite();
        while (((ch = sdePeek()) >= '0') && (ch <= '9')) {
            sdeAdvance();
            value = (value * 10) + ch - '0';
        }
        ignoreWhite();
        return value;
    }

    private void storeFile(int fileId, String sourceName, String sourcePath) {
        assureFileTableSize();
        fileTable[fileIndex].fileId = fileId;
        fileTable[fileIndex].sourceName = sourceName;
        fileTable[fileIndex].sourcePath = sourcePath;
        ++fileIndex;
    }

    private void fileLine(void) {
        int hasAbsolute = 0; /* acts as boolean */
        int fileId;
        String sourceName;
        String sourcePath = null;

        /* is there an absolute filename? */
        if (sdePeek() == '+') {
            sdeAdvance();
            hasAbsolute = 1;
        }
        fileId = readNumber();
        sourceName = readLine();
        if (hasAbsolute == 1) {
            sourcePath = readLine();
        }
        storeFile(fileId, sourceName, sourcePath);
    }

    private void storeLine(int jplsStart, int jplsEnd, int jplsLineInc,
                  int njplsStart, int njplsEnd, int fileId) {
        assureLineTableSize();
        lineTable[lineIndex].jplsStart = jplsStart;
        lineTable[lineIndex].jplsEnd = jplsEnd;
        lineTable[lineIndex].jplsLineInc = jplsLineInc;
        lineTable[lineIndex].njplsStart = njplsStart;
        lineTable[lineIndex].njplsEnd = njplsEnd;
        lineTable[lineIndex].fileId = fileId;
        ++lineIndex;
    }

    /**
     * Parse line translation info.  Syntax is
     *     <NJ-start-line> [ #  ] [ ,  ] :
     *                 <J-start-line> [ ,  ] CR
     */
    private void lineLine(void) {
        int lineCount = 1;
        int lineIncrement = 1;
        int njplsStart;
        int jplsStart;

        njplsStart = readNumber();

        /* is there a fileID? */
        if (sdePeek() == '#') {
            sdeAdvance();
            currentFileId = readNumber();
        }

        /* is there a line count? */
        if (sdePeek() == ',') {
            sdeAdvance();
            lineCount = readNumber();
        }

        if (sdeRead() != ':') {
            syntax("expected ':'");
        }
        jplsStart = readNumber();
        if (sdePeek() == ',') {
            sdeAdvance();
            lineIncrement = readNumber();
        }
        ignoreLine(); /* flush the rest */

        storeLine(jplsStart,
                  jplsStart + (lineCount * lineIncrement) -1,
                  lineIncrement,
                  njplsStart,
                  njplsStart + lineCount -1,
                  currentFileId);
    }

    /**
     * Until the next stratum section, everything after this
     * is in stratumId - so, store the current indicies.
     */
    private void storeStratum(String stratumId) {
        /* remove redundant strata */
        if (stratumIndex > 0) {
            if ((stratumTable[stratumIndex-1].fileIndex
                                            == fileIndex) &&
                (stratumTable[stratumIndex-1].lineIndex
                                            == lineIndex)) {
                /* nothing changed overwrite it */
                --stratumIndex;
            }
        }
        /* store the results */
        assureStratumTableSize();
        stratumTable[stratumIndex].id = stratumId;
        stratumTable[stratumIndex].fileIndex = fileIndex;
        stratumTable[stratumIndex].lineIndex = lineIndex;
        ++stratumIndex;
        currentFileId = 0;
    }

    /**
     * The beginning of a stratum's info
     */
    private void stratumSection(void) {
        storeStratum(readLine());
    }

    private void fileSection(void) {
        ignoreLine();
        while (sdePeek() != '*') {
            fileLine();
        }
    }

    private void lineSection(void) {
        ignoreLine();
        while (sdePeek() != '*') {
            lineLine();
        }
    }

    /**
     * Ignore a section we don't know about.
     */
    private void ignoreSection(void) {
        ignoreLine();
        while (sdePeek() != '*') {
            ignoreLine();
        }
    }

    /**
     * A base "Java" stratum is always available, though
     * it is not in the SourceDebugExtension.
     * Create the base stratum.
     */
    private void createJavaStratum(void) {
        baseStratumIndex = stratumIndex;
        storeStratum(BASE_STRATUM_NAME);
        storeFile(1, jplsFilename, NullString);
        /* JPL line numbers cannot exceed 65535 */
        storeLine(1, 65536, 1, 1, 65536, 1);
        storeStratum("Aux"); /* in case they don't declare */
    }

    /**
     * Decode a SourceDebugExtension which is in SourceMap format.
     * This is the entry point into the recursive descent parser.
     */
    private void decode(void) {
        /* check for "SMAP" - allow EOF if not ours */
        if (strlen(sourceDebugExtension) <= 4 ||
            (sdeRead() != 'S') ||
            (sdeRead() != 'M') ||
            (sdeRead() != 'A') ||
            (sdeRead() != 'P')) {
            return; /* not our info */
        }
        ignoreLine(); /* flush the rest */
        jplsFilename = readLine();
        defaultStratumId = readLine();
        createJavaStratum();
        while (true) {
            if (sdeRead() != '*') {
                syntax("expected '*'");
            }
            switch (sdeRead()) {
                case 'S':
                    stratumSection();
                    break;
                case 'F':
                    fileSection();
                    break;
                case 'L':
                    lineSection();
                    break;
                case 'E':
                    /* set end points */
                    storeStratum("*terminator*");
                    sourceMapIsValid = true;
                    return;
                default:
                    ignoreSection();
            }
        }
    }

    /***************** query functions ***********************/

    private int stiLineTableIndex(int sti, int jplsLine) {
        int i;
        int lineIndexStart;
        int lineIndexEnd;

        lineIndexStart = stratumTable[sti].lineIndex;
        /* one past end */
        lineIndexEnd = stratumTable[sti+1].lineIndex;
        for (i = lineIndexStart; i < lineIndexEnd; ++i) {
            if ((jplsLine >= lineTable[i].jplsStart) &&
                            (jplsLine <= lineTable[i].jplsEnd)) {
                return i;
            }
        }
        return -1;
    }

    private int stiLineNumber(int sti, int lti, int jplsLine) {
        return lineTable[lti].njplsStart +
                (((jplsLine - lineTable[lti].jplsStart) /
                                   lineTable[lti].jplsLineInc));
    }

    private int fileTableIndex(int sti, int fileId) {
        int i;
        int fileIndexStart = stratumTable[sti].fileIndex;
        /* one past end */
        int fileIndexEnd = stratumTable[sti+1].fileIndex;
        for (i = fileIndexStart; i < fileIndexEnd; ++i) {
            if (fileTable[i].fileId == fileId) {
                return i;
            }
        }
        return -1;
    }

    private int stiFileTableIndex(int sti, int lti) {
        return fileTableIndex(sti, lineTable[lti].fileId);
    }

    private jboolean isValid(void) {
        return sourceMapIsValid;
    }

Other Java examples (source code examples)

Here is a short list of links related to this Java SDE.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.