mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-07-08 06:50:35 +08:00
Resync new repository with old repo r5166
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5153 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
############################################################################
|
||||
# pascal/Makefile
|
||||
#
|
||||
# Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name NuttX nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
#
|
||||
# Directories
|
||||
#
|
||||
PASDIR = ${shell pwd}
|
||||
PASCAL = $(PASDIR)/..
|
||||
|
||||
include $(PASCAL)/Make.config
|
||||
include $(PASCAL)/Make.defs
|
||||
|
||||
INCDIR = $(PASCAL)/include
|
||||
LIBDIR = $(PASCAL)/lib
|
||||
BINDIR-$(CONFIG_INSN16) = $(PASCAL)/bin16
|
||||
BINDIR-$(CONFIG_INSN32) = $(PASCAL)/bin32
|
||||
|
||||
#
|
||||
# Objects and targets
|
||||
#
|
||||
PASSRCS = pas.c pprgm.c punit.c pblck.c pstm.c pexpr.c \
|
||||
pcexpr.c pproc.c pffunc.c pcfunc.c pgen.c ptkn.c \
|
||||
ptbl.c perr.c
|
||||
PASOBJS = $(PASSRCS:.c=.o)
|
||||
|
||||
OBJS = $(PASOBJS)
|
||||
|
||||
all: pascal
|
||||
.PHONY: all pascal clean
|
||||
|
||||
$(OBJS): %.o: %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
check_libs:
|
||||
@if [ ! -f $(LIBDIR)/libpoff.a ] ; then \
|
||||
echo "$(LIBDIR)/libpoff.a does not exist" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@if [ ! -f $(LIBDIR)/libpas.a ] ; then \
|
||||
echo "$(LIBDIR)/libpas.a does not exist" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
@if [ ! -f $(LIBDIR)/libinsn.a ] ; then \
|
||||
echo "$(LIBDIR)/libinsn.a does not exist" ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
|
||||
$(BINDIR-y)/pascal: check_libs $(PASOBJS)
|
||||
$(CC) -o $@ $(LDFLAGS) $(PASOBJS) -linsn -lpoff -lpas -lm
|
||||
|
||||
pascal: $(BINDIR-y)/pascal
|
||||
|
||||
clean:
|
||||
$(RM) pascal *.o core *~
|
||||
@@ -0,0 +1,538 @@
|
||||
/**********************************************************************
|
||||
* pas.c
|
||||
* Main process
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Included Files
|
||||
**********************************************************************/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "podefs.h"
|
||||
#include "pedefs.h"
|
||||
|
||||
#include "pas.h"
|
||||
#include "paslib.h" /* For extension */
|
||||
#include "pproc.h" /* For primeBuiltInProcedures */
|
||||
#include "pfunc.h" /* For primeBuiltInFunctions */
|
||||
#include "ptkn.h" /* For primeTokenizer */
|
||||
#include "ptbl.h" /* For primeSymbolTable */
|
||||
#include "pofflib.h" /* For poffInitializeForOutput() */
|
||||
#include "poff.h" /* For POFF definitions */
|
||||
#include "pprgm.h" /* for program() */
|
||||
#include "punit.h" /* for unit() */
|
||||
#include "perr.h" /* for error() */
|
||||
|
||||
/**********************************************************************
|
||||
* Pre-processor Definitions
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Global Variables
|
||||
**********************************************************************/
|
||||
|
||||
/* Unitialized Global Data */
|
||||
|
||||
uint16_t token; /* Current token */
|
||||
uint16_t tknSubType; /* Extended token type */
|
||||
int32_t tknInt; /* Integer token value */
|
||||
double tknReal; /* Real token value */
|
||||
STYPE *tknPtr; /* Pointer to symbol token*/
|
||||
WTYPE withRecord; /* RECORD used with WITH statement */
|
||||
FTYPE files[MAX_FILES+1]; /* File Table */
|
||||
fileState_t fileState[MAX_INCL]; /* State of all open files */
|
||||
|
||||
/* sourceFileName : Program name from command line
|
||||
* includePath[] : Pathes to search when including file
|
||||
*/
|
||||
|
||||
char *sourceFileName;
|
||||
char *includePath[MAX_INCPATHES];
|
||||
|
||||
poffHandle_t poffHandle; /* Handle for POFF object */
|
||||
|
||||
FILE *poffFile; /* Pass1 POFF output file */
|
||||
FILE *lstFile; /* List File pointer */
|
||||
FILE *errFile; /* Error file pointer */
|
||||
|
||||
/* Initialized Global Data */
|
||||
|
||||
int16_t level = 0; /* Static nesting level */
|
||||
int16_t includeIndex = 0; /* Include file index */
|
||||
int16_t nIncPathes = 0; /* Number pathes in includePath[] */
|
||||
uint16_t label = 0; /* Last label number */
|
||||
int16_t nsym = 0; /* Number symbol table entries */
|
||||
int16_t nconst = 0; /* Number constant table entries */
|
||||
int16_t sym_strt = 0; /* Symbol search start index */
|
||||
int16_t const_strt = 0; /* Constant search start index */
|
||||
int16_t err_count = 0; /* Error counter */
|
||||
int16_t nfiles = 0; /* Program file counter */
|
||||
int32_t warn_count = 0; /* Warning counter */
|
||||
int32_t dstack = 0; /* data stack size */
|
||||
|
||||
/**********************************************************************
|
||||
* Private Type Definitions
|
||||
**********************************************************************/
|
||||
|
||||
struct outFileDesc_s
|
||||
{
|
||||
const char *extension;
|
||||
const char *flags;
|
||||
FILE **stream;
|
||||
};
|
||||
typedef struct outFileDesc_s outFileDesc_t;
|
||||
|
||||
/**********************************************************************
|
||||
* Private Variables
|
||||
**********************************************************************/
|
||||
|
||||
static const outFileDesc_t outFiles[] =
|
||||
{
|
||||
{ "o1", "wb", &poffFile }, /* Pass 1 POFF object file */
|
||||
#if LSTTOFILE
|
||||
{ "lst", "w", &lstFile }, /* List file */
|
||||
#endif
|
||||
{ "err", "w", &errFile }, /* Error file */
|
||||
{ NULL, NULL } /* (terminates list */
|
||||
};
|
||||
|
||||
static const char *programName;
|
||||
|
||||
/***********************************************************************
|
||||
* Private Function Prototypes
|
||||
***********************************************************************/
|
||||
|
||||
static void closeFiles(void);
|
||||
static void openOutputFiles(void);
|
||||
static void showUsage(void);
|
||||
static void parseArguments(int argc, char **argv);
|
||||
|
||||
/***********************************************************************
|
||||
* Private Functions
|
||||
***********************************************************************/
|
||||
|
||||
static void closeFiles(void)
|
||||
{
|
||||
const outFileDesc_t *outFile;
|
||||
|
||||
/* Close input source files */
|
||||
|
||||
for(; includeIndex >= 0; includeIndex--)
|
||||
{
|
||||
if (FP->stream)
|
||||
{
|
||||
(void)fclose(FP->stream);
|
||||
FP->stream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close output files */
|
||||
|
||||
for (outFile = outFiles; outFile->extension; outFile++)
|
||||
{
|
||||
if (*outFile->stream)
|
||||
{
|
||||
(void)fclose(*outFile->stream);
|
||||
*outFile->stream = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void openOutputFiles(void)
|
||||
{
|
||||
const outFileDesc_t *outFile;
|
||||
char tmpname[FNAME_SIZE+1];
|
||||
|
||||
/* Open output files */
|
||||
|
||||
for (outFile = outFiles; outFile->extension; outFile++)
|
||||
{
|
||||
/* Generate an output file name from the source file
|
||||
* name and an extension associated with the output file.
|
||||
*/
|
||||
|
||||
(void)extension(sourceFileName, outFile->extension, tmpname, 1);
|
||||
*outFile->stream = fopen(tmpname, outFile->flags);
|
||||
if (*outFile->stream == NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not open output file '%s': %s\n",
|
||||
tmpname, strerror(errno));
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void signalHandler(int signo)
|
||||
{
|
||||
#ifdef _GNU_SOURCE
|
||||
fprintf(errFile, "Received signal: %s\n", strsignal(signo));
|
||||
fprintf(lstFile, "Received signal: %s\n", strsignal(signo));
|
||||
#else
|
||||
fprintf(errFile, "Received signal %d\n", signo);
|
||||
fprintf(lstFile, "Received signal %d\n", signo);
|
||||
#endif
|
||||
closeFiles();
|
||||
error(eRCVDSIGNAL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void primeSignalHandlers(void)
|
||||
{
|
||||
(void)signal(SIGHUP, signalHandler);
|
||||
(void)signal(SIGINT, signalHandler);
|
||||
(void)signal(SIGQUIT, signalHandler);
|
||||
(void)signal(SIGILL, signalHandler);
|
||||
(void)signal(SIGABRT, signalHandler);
|
||||
(void)signal(SIGSEGV, signalHandler);
|
||||
(void)signal(SIGTERM, signalHandler);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void showUsage(void)
|
||||
{
|
||||
fprintf(stderr, "USAGE:\n");
|
||||
fprintf(stderr, " %s [options] <filename>\n", programName);
|
||||
fprintf(stderr, "[options]\n");
|
||||
fprintf(stderr, " -I<include-path>\n");
|
||||
fprintf(stderr, " Search in <include-path> for additional file\n");
|
||||
fprintf(stderr, " A maximum of %d pathes may be specified\n",
|
||||
MAX_INCPATHES);
|
||||
fprintf(stderr, " (default is current directory)\n");
|
||||
closeFiles();
|
||||
exit(1);
|
||||
} /* end showUsage */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void parseArguments(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
programName = argv[0];
|
||||
|
||||
/* Check for existence of at least the filename argument */
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Invalid number of arguments\n");
|
||||
showUsage();
|
||||
}
|
||||
|
||||
/* Parse any optional command line arguments */
|
||||
|
||||
for (i = 1; i < argc-1; i++)
|
||||
{
|
||||
char *ptr = argv[i];
|
||||
if (ptr[0] == '-')
|
||||
{
|
||||
switch (ptr[1])
|
||||
{
|
||||
case 'I' :
|
||||
if (nIncPathes >= MAX_INCPATHES)
|
||||
{
|
||||
fprintf(stderr, "Unrecognized [option]\n");
|
||||
showUsage();
|
||||
}
|
||||
else
|
||||
{
|
||||
includePath[nIncPathes] = &ptr[2];
|
||||
nIncPathes++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unrecognized [option]\n");
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unrecognized [option]\n");
|
||||
showUsage();
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the Pascal program name from the command line */
|
||||
|
||||
sourceFileName = argv[argc-1];
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Public Functions
|
||||
***********************************************************************/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char filename [FNAME_SIZE+1];
|
||||
|
||||
/* Parse command line arguments */
|
||||
|
||||
parseArguments(argc, argv);
|
||||
|
||||
/* Open all output files */
|
||||
|
||||
openOutputFiles();
|
||||
|
||||
#if !LSTTOFILE
|
||||
lstFile = stdout;
|
||||
#endif
|
||||
|
||||
/* Open source file -- Use .PAS or command line extension, if supplied */
|
||||
|
||||
(void)extension(sourceFileName, "PAS", filename, 0);
|
||||
fprintf(errFile, "%01x=%s\n", FP->include, filename);
|
||||
|
||||
memset(FP, 0, sizeof(fileState_t));
|
||||
FP->stream = fopen(filename, "r");
|
||||
if (!FP->stream)
|
||||
{
|
||||
errmsg("Could not open source file '%s': %s\n",
|
||||
filename, strerror(errno));
|
||||
showUsage();
|
||||
}
|
||||
|
||||
/* Initialization */
|
||||
|
||||
primeSignalHandlers();
|
||||
primeSymbolTable(MAX_SYM);
|
||||
primeBuiltInProcedures();
|
||||
primeBuiltInFunctions();
|
||||
primeTokenizer(MAX_STRINGS);
|
||||
|
||||
/* Initialize the POFF object */
|
||||
|
||||
poffHandle = poffCreateHandle();
|
||||
if (poffHandle == NULL)
|
||||
fatal(eNOMEMORY);
|
||||
|
||||
/* Save the soure file name in the POFF output file */
|
||||
|
||||
FP->include = poffAddFileName(poffHandle, filename);
|
||||
|
||||
/* Define standard input/output file characteristics */
|
||||
|
||||
files[0].defined = -1;
|
||||
files[0].flevel = level;
|
||||
files[0].ftype = sCHAR;
|
||||
files[0].faddr = dstack;
|
||||
files[0].fsize = sCHAR_SIZE;
|
||||
dstack += sCHAR_SIZE;
|
||||
|
||||
/* We need the following in order to calculate relative stack positions. */
|
||||
|
||||
FP->dstack = dstack;
|
||||
|
||||
/* Indicate that no WITH statement has been processed */
|
||||
|
||||
memset(&withRecord, 0, sizeof(WTYPE));
|
||||
|
||||
/* Process the pascal program
|
||||
*
|
||||
* FORM: pascal = program | unit
|
||||
* FORM: program = program-heading ';' [uses-section ] block '.'
|
||||
* FORM: program-heading = 'program' identifier [ '(' identifier-list ')' ]
|
||||
* FORM: unit = unit-heading ';' interface-section implementation-section init-section
|
||||
* FORM: unit-heading = 'unit' identifer
|
||||
*/
|
||||
|
||||
getToken();
|
||||
if (token == tPROGRAM)
|
||||
{
|
||||
/* Compile a pascal program */
|
||||
|
||||
FP->kind = eIsProgram;
|
||||
FP->section = eIsProgramSection;
|
||||
getToken();
|
||||
program();
|
||||
}
|
||||
else if (token == tUNIT)
|
||||
{
|
||||
/* Compile a pascal unit */
|
||||
|
||||
FP->kind = eIsUnit;
|
||||
FP->section = eIsOtherSection;
|
||||
getToken();
|
||||
unitImplementation();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Expected 'program' or 'unit' */
|
||||
|
||||
error(ePROGRAM);
|
||||
}
|
||||
|
||||
/* Dump the symbol table content (debug only) */
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
dumpTables();
|
||||
#endif
|
||||
|
||||
/* Write the POFF output file */
|
||||
|
||||
poffWriteFile(poffHandle, poffFile);
|
||||
poffDestroyHandle(poffHandle);
|
||||
|
||||
/* Close all output files */
|
||||
|
||||
closeFiles();
|
||||
|
||||
/* Write Closing Message */
|
||||
|
||||
if (warn_count > 0)
|
||||
{
|
||||
printf(" %ld Warnings Issued\n", warn_count);
|
||||
} /* end if */
|
||||
|
||||
if (err_count > 0)
|
||||
{
|
||||
printf(" %d Errors Detected\n\n", err_count);
|
||||
return -1;
|
||||
} /* end if */
|
||||
|
||||
return 0;
|
||||
|
||||
} /* end main */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void openNestedFile(const char *fileName)
|
||||
{
|
||||
fileState_t *prev = FP;
|
||||
char fullpath[FNAME_SIZE + 1];
|
||||
int i;
|
||||
|
||||
/* Make sure we can handle another nested file */
|
||||
|
||||
if (++includeIndex >= MAX_INCL) fatal(eOVF);
|
||||
else
|
||||
{
|
||||
/* Clear the file state structure for the new include level */
|
||||
|
||||
memset(FP, 0, sizeof(fileState_t));
|
||||
|
||||
/* Try all source include pathes until we find the file or
|
||||
* until we exhaust the include path list.
|
||||
*/
|
||||
|
||||
for (i = 0; ; i++)
|
||||
{
|
||||
/* Open the nested file -- try all possible pathes or
|
||||
* until we successfully open the file.
|
||||
*/
|
||||
|
||||
/* The final path that we will try is the current directory */
|
||||
|
||||
if (i == nIncPathes)
|
||||
{
|
||||
sprintf(fullpath, "./%s", fileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(fullpath, "%s/%s", includePath[i], fileName);
|
||||
}
|
||||
|
||||
FP->stream = fopen (fullpath, "rb");
|
||||
if (!FP->stream)
|
||||
{
|
||||
/* We failed to open the file. If there are no more
|
||||
* include pathes to examine (including the current directory),
|
||||
* then error out. This is fatal. Otherwise, continue
|
||||
* looping.
|
||||
*/
|
||||
|
||||
if (i == nIncPathes)
|
||||
{
|
||||
errmsg("Failed to open '%s': %s\n",
|
||||
fileName, strerror(errno));
|
||||
fatal(eINCLUDE);
|
||||
break; /* Won't get here */
|
||||
}
|
||||
} /* end else if */
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Setup the newly opened file */
|
||||
|
||||
fprintf(errFile, "%01x=%s\n", FP->include, fullpath);
|
||||
FP->include = poffAddFileName(poffHandle, fullpath);
|
||||
|
||||
/* The caller may change this, but the default behavior is
|
||||
* to inherit the kind and section of the including file
|
||||
* and the current data stack offset.
|
||||
*/
|
||||
|
||||
FP->kind = prev->kind;
|
||||
FP->section = prev->section;
|
||||
FP->dstack = dstack;
|
||||
|
||||
rePrimeTokenizer();
|
||||
|
||||
/* Get the first token from the file */
|
||||
|
||||
getToken();
|
||||
} /* end else */
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void closeNestedFile(void)
|
||||
{
|
||||
if (FP->stream)
|
||||
{
|
||||
(void)fclose(FP->stream);
|
||||
includeIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -0,0 +1,116 @@
|
||||
/***************************************************************************
|
||||
* pas.h
|
||||
* External Declarations associated with pas.c
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PAS_H
|
||||
#define __PAS_H
|
||||
|
||||
/***************************************************************************
|
||||
* Compilation Switches
|
||||
***************************************************************************/
|
||||
|
||||
#define LSTTOFILE 1
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include "pasdefs.h"
|
||||
#include "pofflib.h"
|
||||
|
||||
/***************************************************************************
|
||||
* Pre-processor Definitions
|
||||
***************************************************************************/
|
||||
|
||||
/* This is a helper macro just to make things pretty in the source code */
|
||||
|
||||
#define FP0 (&fileState[0]) /* Main file description */
|
||||
#define FP (&fileState[includeIndex]) /* Current file description */
|
||||
#define FPP (&fileState[includeIndex-1]) /* Previous file description */
|
||||
#define IS_NESTED_UNIT ((includeIndex > 0) && (FP->kind == eIsUnit))
|
||||
|
||||
/***************************************************************************
|
||||
* Global Types
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Global Variable
|
||||
***************************************************************************/
|
||||
|
||||
extern uint16_t token; /* Current token */
|
||||
extern uint16_t tknSubType; /* Extended token type */
|
||||
extern int32_t tknInt; /* Integer token value */
|
||||
extern double tknReal; /* Real token value */
|
||||
extern STYPE *tknPtr; /* Pointer to symbol token */
|
||||
extern FTYPE files[MAX_FILES+1]; /* File Table */
|
||||
extern fileState_t fileState[MAX_INCL]; /* State of all open files */
|
||||
|
||||
/* sourceFileName : Source file name from command line
|
||||
* includePath[] : Pathes to search when including file
|
||||
*/
|
||||
|
||||
extern char *sourceFileName;
|
||||
extern char *includePath[MAX_INCPATHES];
|
||||
|
||||
extern poffHandle_t poffHandle; /* Handle for POFF object */
|
||||
|
||||
extern FILE *poffFile; /* POFF output file */
|
||||
extern FILE *errFile; /* Error file pointer */
|
||||
extern FILE *lstFile; /* List file pointer */
|
||||
|
||||
extern WTYPE withRecord; /* RECORD of WITH statement */
|
||||
extern int16_t level; /* Static nesting level */
|
||||
extern int16_t includeIndex; /* Include file index */
|
||||
extern int16_t nIncPathes; /* Number pathes in includePath[] */
|
||||
extern uint16_t label; /* Last label number */
|
||||
extern int16_t nsym; /* Number symbol table entries */
|
||||
extern int16_t nconst; /* Number constant table entries */
|
||||
extern int16_t sym_strt; /* Symbol search start index */
|
||||
extern int16_t const_strt; /* Constant search start index */
|
||||
extern int16_t err_count; /* Error counter */
|
||||
extern int16_t nfiles; /* Program file counter */
|
||||
extern int32_t warn_count; /* Warning counter */
|
||||
extern int32_t dstack; /* data stack size */
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void openNestedFile (const char *fileName);
|
||||
extern void closeNestedFile (void);
|
||||
|
||||
#endif /* __PAS_H */
|
||||
@@ -0,0 +1,284 @@
|
||||
/***********************************************************************
|
||||
* pascal/pasdefs.h
|
||||
* General definitions for the Pascal Compiler/Optimizer
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __PASDEFS_H
|
||||
#define __PASDEFS_H
|
||||
|
||||
/***********************************************************************
|
||||
* Included Files
|
||||
***********************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h> /* for FILE */
|
||||
#include <config.h>
|
||||
#include "pdefs.h" /* Common definitions */
|
||||
|
||||
/***********************************************************************
|
||||
* Pre-processor Definitions
|
||||
***********************************************************************/
|
||||
|
||||
/* Size Parameters -- some of these can be overridden from the
|
||||
* command line.
|
||||
*/
|
||||
|
||||
#define MAX_SYM (4096)
|
||||
#define MAX_STRINGS (65536)
|
||||
#define MAX_INCL 3 /* Max number of nested include files */
|
||||
#define MAX_FILES 8 /* Max number of opened files */
|
||||
#define FNAME_SIZE 40 /* Max size file name */
|
||||
#define MAX_INCPATHES 8 /* Max number of include pathes */
|
||||
|
||||
/* Bit values for the 'flags' field of the symType_t, symProc_t, and
|
||||
* symVar_t (see below)
|
||||
*/
|
||||
|
||||
#define STYPE_VARSIZE 0x01 /* Type has variable size */
|
||||
#define SPROC_EXTERNAL 0x01 /* Proc/func. is defined externally */
|
||||
#define SVAR_EXTERNAL 0x01 /* Variable is defined externally */
|
||||
|
||||
/***********************************************************************
|
||||
* Public Enumeration Types
|
||||
***********************************************************************/
|
||||
|
||||
/* This enumeration identies what kind of binary object we are creating
|
||||
* with the compilation. At present, we may be generating either a
|
||||
* program binary or a unit binary.
|
||||
*/
|
||||
|
||||
enum fileKind_e
|
||||
{
|
||||
eIsProgram = 0,
|
||||
eIsUnit
|
||||
};
|
||||
typedef enum fileKind_e fileKind_t;
|
||||
|
||||
/* This enumeration determines what part of a file that we are
|
||||
* processing now.
|
||||
*/
|
||||
|
||||
enum fileSection_e
|
||||
{
|
||||
eIsOtherSection = 0, /* Unspecified part of the file */
|
||||
eIsProgramSection, /* Any part of a program file */
|
||||
eIsInterfaceSection, /* INTERFACE section of a unit file */
|
||||
eIsImplementationSection, /* IMPLEMENTATION section of a unit file */
|
||||
eIsInitializationSection, /* INITIALIZATION section of a unit file */
|
||||
};
|
||||
typedef enum fileSection_e fileSection_t;
|
||||
|
||||
/***********************************************************************
|
||||
* Public Structure/Types
|
||||
***********************************************************************/
|
||||
|
||||
/* Reserved word table entry */
|
||||
|
||||
struct R
|
||||
{
|
||||
char *rname; /* pointer to name in string stack */
|
||||
uint8_t rtype; /* reserved word type */
|
||||
uint8_t subtype; /* reserved word extended type */
|
||||
};
|
||||
typedef struct R RTYPE;
|
||||
|
||||
/* Symbol table entry */
|
||||
|
||||
struct symType_s /* for sKind = sTYPE */
|
||||
{
|
||||
uint8_t type; /* specific type */
|
||||
uint8_t rtype; /* reference to type */
|
||||
uint8_t subType; /* constant type for subrange types */
|
||||
uint8_t flags; /* flags to customize a type (see above) */
|
||||
uint32_t asize; /* size of allocated instances of this type */
|
||||
uint32_t rsize; /* size of reference to an instances of this type */
|
||||
int32_t minValue; /* minimum value taken subrange */
|
||||
int32_t maxValue; /* maximum value taken by subrange or scalar */
|
||||
struct S *parent; /* pointer to parent type */
|
||||
};
|
||||
typedef struct symType_s symType_t;
|
||||
|
||||
struct symConst_s /* for sKind == constant type */
|
||||
{
|
||||
union
|
||||
{
|
||||
double f; /* real value */
|
||||
int32_t i; /* integer value */
|
||||
} val;
|
||||
struct S *parent; /* pointer to parent type */
|
||||
};
|
||||
typedef struct symConst_s symConst_t;
|
||||
|
||||
struct symStringConst_s /* for sKind == sSTRING_CONST */
|
||||
{
|
||||
uint32_t offset; /* RO data section offset of string */
|
||||
uint32_t size; /* length of string in bytes */
|
||||
};
|
||||
typedef struct symStringConst_s symStringConst_t;
|
||||
|
||||
struct symVarString_s /* for sKind == sSTRING */
|
||||
{
|
||||
uint16_t label; /* label at string declaration */
|
||||
uint16_t size; /* valid length of string in bytes */
|
||||
uint16_t alloc; /* max length of string in bytes */
|
||||
};
|
||||
typedef struct symVarString_s symVarString_t;
|
||||
|
||||
struct symLabel_s /* for sKind == sLABEL */
|
||||
{
|
||||
uint16_t label; /* label number */
|
||||
bool unDefined; /* set false when defined */
|
||||
};
|
||||
typedef struct symLabel_s symLabel_t;
|
||||
|
||||
struct symVar_s /* for sKind == type identifier */
|
||||
{
|
||||
int32_t offset; /* Data stack offset */
|
||||
uint32_t size; /* Size of variable */
|
||||
uint8_t flags; /* flags to customize a variable (see above) */
|
||||
uint32_t symIndex; /* POFF symbol table index (if undefined) */
|
||||
struct S *parent; /* pointer to parent type */
|
||||
};
|
||||
typedef struct symVar_s symVar_t;
|
||||
|
||||
struct symProc_s /* for sKind == sPROC or sFUNC */
|
||||
{
|
||||
uint16_t label; /* entry point label */
|
||||
uint16_t nParms; /* number of parameters that follow */
|
||||
uint8_t flags; /* flags to customize a proc/func (see above) */
|
||||
uint32_t symIndex; /* POFF symbol table index (if undefined) */
|
||||
struct S *parent; /* pointer to parent type (sFUNC only) */
|
||||
};
|
||||
typedef struct symProc_s symProc_t;
|
||||
|
||||
struct symRecord_s /* for sKind == sRECORD_OBJECT */
|
||||
{
|
||||
uint32_t size; /* size of this field */
|
||||
uint32_t offset; /* offset into the RECORD */
|
||||
struct S *record; /* pointer to parent sRECORD type */
|
||||
struct S *parent; /* pointer to parent field type */
|
||||
};
|
||||
typedef struct symRecord_s symRecord_t;
|
||||
|
||||
struct S
|
||||
{
|
||||
char *sName; /* pointer to name in string stack */
|
||||
uint8_t sKind; /* kind of symbol */
|
||||
uint8_t sLevel; /* static nesting level */
|
||||
union
|
||||
{
|
||||
symType_t t; /* for type definitions */
|
||||
symConst_t c; /* for constants */
|
||||
symStringConst_t s; /* for strings of constant size*/
|
||||
symVarString_t vs; /* for strings of variable size*/
|
||||
uint16_t fileNumber; /* for files */
|
||||
symLabel_t l; /* for labels */
|
||||
symVar_t v; /* for variables */
|
||||
symProc_t p; /* for functions & procedures */
|
||||
symRecord_t r; /* for files of RECORDS */
|
||||
} sParm;
|
||||
};
|
||||
typedef struct S STYPE;
|
||||
|
||||
/* WITH structure */
|
||||
|
||||
struct W
|
||||
{
|
||||
uint8_t level; /* static nesting level */
|
||||
bool pointer; /* true if offset is to pointer to RECORD */
|
||||
bool varParm; /* true if VAR param (+pointer) */
|
||||
int32_t offset; /* Data stack offset */
|
||||
uint16_t index; /* RECORD offset (if pointer) */
|
||||
STYPE *parent; /* pointer to parent RECORD type */
|
||||
};
|
||||
typedef struct W WTYPE;
|
||||
|
||||
/* File table record */
|
||||
|
||||
struct F
|
||||
{
|
||||
int16_t defined;
|
||||
int16_t flevel;
|
||||
int16_t ftype;
|
||||
int32_t faddr;
|
||||
int16_t fsize;
|
||||
};
|
||||
typedef struct F FTYPE;
|
||||
|
||||
/* This structure captures the parsing state of the compiler for a particular
|
||||
* file. Since multiple, nested files can be processed, this represents
|
||||
* only level in the "stack" of nested files.
|
||||
*/
|
||||
|
||||
struct fileState_s
|
||||
{
|
||||
/* These fields are managed by the higher level parsing logic
|
||||
*
|
||||
* stream - Stream pointer the input stream associated with this
|
||||
* file.
|
||||
* kind - Kind of file we are processing. If include > 0,
|
||||
* this should be eIsUnit.
|
||||
* section - This is the part of the program that we are parsing
|
||||
* now.
|
||||
* dstack - Level zero dstack offset at the time the unit was
|
||||
* included. This is used to convert absolute program
|
||||
* stack offsets into relative unit stack offsets.
|
||||
* include - Is a unique number that identifies the file. In
|
||||
* POFF ouput file, this would be the index to the
|
||||
* entry in the .files section.
|
||||
*/
|
||||
|
||||
FILE *stream;
|
||||
fileKind_t kind;
|
||||
fileSection_t section;
|
||||
int32_t dstack;
|
||||
int16_t include;
|
||||
|
||||
/* These fields are managed by the tokenizer. These are all
|
||||
* initialized by primeTokenizer().
|
||||
*
|
||||
* buffer[] - Holds the current input line
|
||||
* line - Is the line number in this file for the current line
|
||||
* cp - Is the current pointer into buffer[]
|
||||
*/
|
||||
|
||||
uint32_t line;
|
||||
unsigned char *cp;
|
||||
unsigned char buffer[LINE_SIZE + 1];
|
||||
};
|
||||
typedef struct fileState_s fileState_t;
|
||||
|
||||
#endif /* __PASDEFS_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
* pblck.h
|
||||
* External Declarations associated with pblck.c
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PBLCK_H
|
||||
#define __PBLCK_H
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void block(void);
|
||||
extern void declarationGroup(int32_t beginLabel);
|
||||
extern void constantDefinitionGroup(void);
|
||||
extern void typeDefinitionGroup(void);
|
||||
extern void variableDeclarationGroup(void);
|
||||
extern int16_t formalParameterList(STYPE *procPtr);
|
||||
|
||||
#endif /* __PBLCK_H */
|
||||
@@ -0,0 +1,576 @@
|
||||
/***************************************************************
|
||||
* pexpr.c
|
||||
* Constant expression evaluation
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* Included Files
|
||||
***************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "pedefs.h"
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pas.h"
|
||||
#include "pstm.h"
|
||||
#include "pexpr.h"
|
||||
#include "pfunc.h"
|
||||
#include "ptkn.h"
|
||||
#include "perr.h"
|
||||
|
||||
/***************************************************************
|
||||
* Pre-processor Definitions
|
||||
***************************************************************/
|
||||
|
||||
#define ADDRESS_DEREFERENCE 0x01
|
||||
#define ADDRESS_FACTOR 0x02
|
||||
#define INDEXED_FACTOR 0x04
|
||||
#define VAR_PARM_FACTOR 0x08
|
||||
|
||||
#define intTrunc(x) ((x) & (~(sINT_SIZE)))
|
||||
|
||||
#define isRelationalOperator(t) \
|
||||
(((t) == tEQ) || ((t) == tNE) || \
|
||||
((t) == tLT) || ((t) == tLE) || \
|
||||
((t) == tGT) || ((t) == tGE) || \
|
||||
((t) == tIN))
|
||||
|
||||
#define isRelationalType(t) \
|
||||
(((t) == tINT_CONST) || ((t) == tCHAR_CONST) || \
|
||||
(((t) == tBOOLEAN_CONST) || ((t) == tREAL_CONST)))
|
||||
|
||||
#define isAdditiveType(t) \
|
||||
(((t) == tINT_CONST) || ((t) == tREAL_CONST))
|
||||
|
||||
#define isMultiplicativeType(t) \
|
||||
(((t) == tINT_CONST) || ((t) == tREAL_CONST))
|
||||
|
||||
#define isLogicalType(t) \
|
||||
(((t) == tINT_CONST) || ((t) == tBOOLEAN_CONST))
|
||||
|
||||
/***************************************************************
|
||||
* Private Type Declarations
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* Private Function Prototypes
|
||||
***************************************************************/
|
||||
|
||||
static void constantSimpleExpression(void);
|
||||
static void constantTerm(void);
|
||||
static void constantFactor(void);
|
||||
|
||||
/***************************************************************
|
||||
* Global Variables
|
||||
***************************************************************/
|
||||
|
||||
int constantToken;
|
||||
int32_t constantInt;
|
||||
double constantReal;
|
||||
char *constantStart;
|
||||
|
||||
/***************************************************************
|
||||
* Private Variables
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************/
|
||||
/* Evaluate a simple expression of constant values */
|
||||
|
||||
void constantExpression(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantExpression]");
|
||||
|
||||
/* Get the value of a simple constant expression */
|
||||
|
||||
constantSimpleExpression();
|
||||
|
||||
/* Is it followed by a relational operator? */
|
||||
|
||||
if (isRelationalOperator(token) && isRelationalType(constantToken))
|
||||
{
|
||||
int simple1 = constantToken;
|
||||
int32_t simple1Int = constantInt;
|
||||
double simple1Real = constantReal;
|
||||
int operator = token;
|
||||
|
||||
/* Get the second simple expression */
|
||||
|
||||
constantSimpleExpression();
|
||||
if (simple1 != constantToken)
|
||||
{
|
||||
/* Handle the case where the 1st argument is REAL and the
|
||||
* second is INTEGER. */
|
||||
|
||||
if ((simple1 == tREAL_CONST) && (constantToken == tINT_CONST))
|
||||
{
|
||||
simple1Real = (double)simple1Int;
|
||||
simple1 = tREAL_CONST;
|
||||
}
|
||||
|
||||
/* Handle the case where the 1st argument is Integer and the
|
||||
* second is REAL. */
|
||||
|
||||
else if ((simple1 == tINT_CONST) && (constantToken == tREAL_CONST))
|
||||
{
|
||||
constantReal = (double)constantInt;
|
||||
}
|
||||
|
||||
/* Allow the case of <scalar type> IN <set type>
|
||||
* Otherwise, the two terms must agree in type
|
||||
* -- NOT YET implemented.
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
error(eEXPRTYPE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate the comparison by type */
|
||||
|
||||
switch (simple1)
|
||||
{
|
||||
case tINT_CONST :
|
||||
case tCHAR_CONST :
|
||||
case tBOOLEAN_CONST :
|
||||
switch (operator)
|
||||
{
|
||||
case tEQ :
|
||||
constantInt = (simple1Int == constantInt);
|
||||
break;
|
||||
case tNE :
|
||||
constantInt = (simple1Int != constantInt);
|
||||
break;
|
||||
case tLT :
|
||||
constantInt = (simple1Int < constantInt);
|
||||
break;
|
||||
case tLE :
|
||||
constantInt = (simple1Int <= constantInt);
|
||||
break;
|
||||
case tGT :
|
||||
constantInt = (simple1Int > constantInt);
|
||||
break;
|
||||
case tGE :
|
||||
constantInt = (simple1Int >= constantInt);
|
||||
break;
|
||||
case tIN :
|
||||
/* Not yet */
|
||||
default :
|
||||
error(eEXPRTYPE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case tREAL_CONST:
|
||||
switch (operator)
|
||||
{
|
||||
case tEQ :
|
||||
constantInt = (simple1Real == constantReal);
|
||||
break;
|
||||
case tNE :
|
||||
constantInt = (simple1Real != constantReal);
|
||||
break;
|
||||
case tLT :
|
||||
constantInt = (simple1Real < constantReal);
|
||||
break;
|
||||
case tLE :
|
||||
constantInt = (simple1Real <= constantReal);
|
||||
break;
|
||||
case tGT :
|
||||
constantInt = (simple1Real > constantReal);
|
||||
break;
|
||||
case tGE :
|
||||
constantInt = (simple1Real >= constantReal);
|
||||
break;
|
||||
case tIN :
|
||||
/* Not yet */
|
||||
default :
|
||||
error(eEXPRTYPE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
error(eEXPRTYPE);
|
||||
break;
|
||||
}
|
||||
|
||||
/* The type resulting from these operations becomes BOOLEAN */
|
||||
|
||||
constantToken = tBOOLEAN_CONST;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* Process Simple Expression */
|
||||
|
||||
static void constantSimpleExpression(void)
|
||||
{
|
||||
int16_t unary = ' ';
|
||||
int term;
|
||||
int32_t termInt;
|
||||
double termReal;
|
||||
|
||||
TRACE(lstFile,"[constantSimpleExpression]");
|
||||
|
||||
/* FORM: [+|-] <term> [{+|-} <term> [{+|-} <term> [...]]] */
|
||||
/* get +/- unary operation */
|
||||
|
||||
if ((token == '+') || (token == '-'))
|
||||
{
|
||||
unary = token;
|
||||
getToken();
|
||||
}
|
||||
|
||||
/* Process first (non-optional) term and apply unary operation */
|
||||
|
||||
constantTerm();
|
||||
term = constantToken;
|
||||
if ((unary != ' ') && !isAdditiveType(term))
|
||||
{
|
||||
error(eINVSIGNEDCONST);
|
||||
}
|
||||
else if (unary == '-')
|
||||
{
|
||||
termInt = -constantInt;
|
||||
termReal = -constantReal;
|
||||
}
|
||||
else
|
||||
{
|
||||
termInt = constantInt;
|
||||
termReal = constantReal;
|
||||
}
|
||||
|
||||
/* Process subsequent (optional) terms and binary operations */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int operator;
|
||||
|
||||
/* Check for binary operator */
|
||||
|
||||
if ((((token == '+') || (token == '-')) )&& isAdditiveType(term))
|
||||
operator = token;
|
||||
else if ((token == tOR) && isLogicalType(term))
|
||||
operator = token;
|
||||
else
|
||||
break;
|
||||
|
||||
/* Get the 2nd term */
|
||||
|
||||
getToken();
|
||||
constantTerm();
|
||||
|
||||
/* Before generating the operation, verify that the types match.
|
||||
* Perform automatic type conversion from INTEGER to REAL as
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
if (term != constantToken)
|
||||
{
|
||||
/* Handle the case where the 1st argument is REAL and the
|
||||
* second is INTEGER. */
|
||||
|
||||
if ((term == tREAL_CONST) && (constantToken == tINT_CONST))
|
||||
{
|
||||
constantReal = (double)constantInt;
|
||||
constantToken = tREAL_CONST;
|
||||
}
|
||||
|
||||
/* Handle the case where the 1st argument is Integer and the
|
||||
* second is REAL. */
|
||||
|
||||
else if ((term == tINT_CONST) && (constantToken == tREAL_CONST))
|
||||
{
|
||||
termReal = (double)termInt;
|
||||
term = tREAL_CONST;
|
||||
}
|
||||
|
||||
/* Otherwise, the two terms must agree in type */
|
||||
|
||||
else
|
||||
{
|
||||
error(eTERMTYPE);
|
||||
}
|
||||
} /* end if */
|
||||
|
||||
|
||||
/* Perform the selected binary operation */
|
||||
|
||||
switch (term)
|
||||
{
|
||||
case tINT_CONST :
|
||||
if (operator == '+')
|
||||
{
|
||||
termInt += constantInt;
|
||||
}
|
||||
else
|
||||
{
|
||||
termInt -= constantInt;
|
||||
}
|
||||
break;
|
||||
|
||||
case tREAL_CONST :
|
||||
if (operator == '+')
|
||||
{
|
||||
termReal += constantReal;
|
||||
}
|
||||
else
|
||||
{
|
||||
termReal -= constantReal;
|
||||
}
|
||||
break;
|
||||
|
||||
case tBOOLEAN_CONST :
|
||||
termInt |= constantInt;
|
||||
break;
|
||||
|
||||
default :
|
||||
error(eEXPRTYPE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
constantToken = term;
|
||||
constantInt = termInt;
|
||||
constantReal = termReal;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* Evaluate a TERM */
|
||||
|
||||
void constantTerm(void)
|
||||
{
|
||||
int operator;
|
||||
int factor;
|
||||
int32_t factorInt;
|
||||
double factorReal;
|
||||
|
||||
TRACE(lstFile,"[constantTerm]");
|
||||
|
||||
/* FORM: <factor> [<operator> <factor>[<operator><factor>[...]]] */
|
||||
|
||||
constantFactor();
|
||||
factor = constantToken;
|
||||
factorInt = constantInt;
|
||||
factorReal = constantReal;
|
||||
for (;;) {
|
||||
/* Check for binary operator */
|
||||
|
||||
if (((token == tMUL) || (token == tMOD)) &&
|
||||
(isMultiplicativeType(factor)))
|
||||
operator = token;
|
||||
else if (((token == tDIV) || (token == tSHL) || (token == tSHR)) &&
|
||||
(factor == tINT_CONST))
|
||||
operator = token;
|
||||
else if ((token == tFDIV) && (factor == tREAL_CONST))
|
||||
operator = token;
|
||||
#if 0
|
||||
else if ((token == tFDIV) && (factor == tINT_CONST))
|
||||
{
|
||||
factorReal = (double)factorInt;
|
||||
factor = tREAL_CONST;
|
||||
operator = token;
|
||||
}
|
||||
#endif
|
||||
else if ((token == tAND) && isLogicalType(factor))
|
||||
operator = token;
|
||||
else
|
||||
{
|
||||
constantToken = factor;
|
||||
constantInt = factorInt;
|
||||
constantReal = factorReal;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the next factor */
|
||||
|
||||
getToken();
|
||||
constantFactor();
|
||||
|
||||
/* Before generating the operation, verify that the types match.
|
||||
* Perform automatic type conversion from INTEGER to REAL as
|
||||
* necessary.
|
||||
*/
|
||||
|
||||
if (factor != constantToken)
|
||||
{
|
||||
/* Handle the case where the 1st argument is REAL and the
|
||||
* second is INTEGER. */
|
||||
|
||||
if ((factor == tREAL_CONST) && (constantToken == tINT_CONST))
|
||||
{
|
||||
constantReal = (double)constantInt;
|
||||
}
|
||||
|
||||
/* Handle the case where the 1st argument is Integer and the
|
||||
* second is REAL. */
|
||||
|
||||
else if ((factor == tINT_CONST) && (constantToken == tREAL_CONST))
|
||||
{
|
||||
factorReal = (double)factorInt;
|
||||
factor = tREAL_CONST;
|
||||
}
|
||||
|
||||
/* Otherwise, the two factors must agree in type */
|
||||
|
||||
else
|
||||
{
|
||||
error(eFACTORTYPE);
|
||||
}
|
||||
} /* end if */
|
||||
|
||||
/* Generate code to perform the selected binary operation */
|
||||
|
||||
switch (operator)
|
||||
{
|
||||
case tMUL :
|
||||
if (factor == tINT_CONST)
|
||||
factorInt *= constantInt;
|
||||
else if (factor == tREAL_CONST)
|
||||
factorReal *= constantReal;
|
||||
else
|
||||
error(eFACTORTYPE);
|
||||
break;
|
||||
|
||||
case tDIV :
|
||||
if (factor == tINT_CONST)
|
||||
factorInt /= constantInt;
|
||||
else
|
||||
error(eFACTORTYPE);
|
||||
break;
|
||||
|
||||
case tFDIV :
|
||||
if (factor == tREAL_CONST)
|
||||
factorReal /= constantReal;
|
||||
else
|
||||
error(eFACTORTYPE);
|
||||
break;
|
||||
|
||||
case tMOD :
|
||||
if (factor == tINT_CONST)
|
||||
factorInt %= constantInt;
|
||||
else if (factor == tREAL_CONST)
|
||||
factorReal = fmod(factorReal, constantReal);
|
||||
else
|
||||
error(eFACTORTYPE);
|
||||
break;
|
||||
|
||||
case tAND :
|
||||
if ((factor == tINT_CONST) || (factor == tBOOLEAN_CONST))
|
||||
factorInt &= constantInt;
|
||||
else
|
||||
error(eFACTORTYPE);
|
||||
break;
|
||||
|
||||
case tSHL :
|
||||
if (factor == tINT_CONST)
|
||||
factorInt <<= constantInt;
|
||||
else
|
||||
error(eFACTORTYPE);
|
||||
break;
|
||||
|
||||
case tSHR :
|
||||
if (factor == tINT_CONST)
|
||||
factorInt >>= constantInt;
|
||||
else
|
||||
error(eFACTORTYPE);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* Process a FACTOR */
|
||||
|
||||
static void constantFactor(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantFactor]");
|
||||
|
||||
/* Process by token type */
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case tINT_CONST :
|
||||
case tBOOLEAN_CONST :
|
||||
case tCHAR_CONST :
|
||||
constantToken = token;
|
||||
constantInt = tknInt;
|
||||
getToken();
|
||||
break;
|
||||
|
||||
case tREAL_CONST :
|
||||
constantToken = token;
|
||||
constantReal = tknReal;
|
||||
getToken();
|
||||
break;
|
||||
|
||||
case tSTRING_CONST :
|
||||
constantToken = token;
|
||||
constantStart = tkn_strt;
|
||||
getToken();
|
||||
break;
|
||||
|
||||
/* Highest Priority Operators */
|
||||
|
||||
case tNOT:
|
||||
getToken();
|
||||
constantFactor();
|
||||
if ((constantToken != tINT_CONST) && (constantToken != tBOOLEAN_CONST))
|
||||
error(eFACTORTYPE);
|
||||
constantInt = ~constantInt;
|
||||
break;
|
||||
|
||||
/* Built-in function? */
|
||||
|
||||
case tFUNC:
|
||||
builtInFunctionOfConstant();
|
||||
break;
|
||||
|
||||
/* Hmmm... Try the standard functions */
|
||||
|
||||
default :
|
||||
error(eINVFACTOR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
/***************************************************************
|
||||
* pcfunc.c
|
||||
* Standard Function operating on constant values
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* Included Files
|
||||
***************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "podefs.h"
|
||||
#include "pfdefs.h"
|
||||
#include "pedefs.h"
|
||||
#include "pxdefs.h"
|
||||
|
||||
#include "pas.h"
|
||||
#include "pexpr.h"
|
||||
#include "pfunc.h"
|
||||
#include "ptkn.h"
|
||||
#include "perr.h"
|
||||
|
||||
/***************************************************************
|
||||
* Private Function Prototypes
|
||||
***************************************************************/
|
||||
|
||||
/* Standard Pascal Functions */
|
||||
|
||||
static void constantAbsFunc(void); /* Integer absolute value */
|
||||
static void constantPredFunc(void);
|
||||
static void constantOrdFunc(void); /* Convert scalar to integer */
|
||||
static void constantSqrFunc(void);
|
||||
static void constantRealFunc(uint8_t fpCode);
|
||||
static void constantSuccFunc(void);
|
||||
static void constantOddFunc(void);
|
||||
static void constantChrFunc(void);
|
||||
static void constantReal2IntFunc(int kind);
|
||||
static void isOrdinalConstant(void);
|
||||
|
||||
/***************************************************************/
|
||||
/* Process a standard Pascal function call */
|
||||
|
||||
void builtInFunctionOfConstant(void)
|
||||
{
|
||||
TRACE(lstFile,"[builtInFunctionFactor]");
|
||||
|
||||
/* Is the token a function? */
|
||||
|
||||
if (token == tFUNC)
|
||||
{
|
||||
/* Yes, process it procedure according to the extended token type */
|
||||
|
||||
switch (tknSubType)
|
||||
{
|
||||
/* Functions which return the same type as their argument */
|
||||
case txABS :
|
||||
constantAbsFunc();
|
||||
break;
|
||||
case txSQR :
|
||||
constantSqrFunc();
|
||||
break;
|
||||
case txPRED :
|
||||
constantPredFunc();
|
||||
break;
|
||||
case txSUCC :
|
||||
constantSuccFunc();
|
||||
break;
|
||||
|
||||
/* Functions returning INTEGER with REAL arguments */
|
||||
|
||||
case txROUND :
|
||||
constantReal2IntFunc(fpROUND);
|
||||
break;
|
||||
case txTRUNC :
|
||||
constantReal2IntFunc(fpTRUNC);
|
||||
break;
|
||||
|
||||
/* Functions returning CHARACTER with INTEGER arguments. */
|
||||
|
||||
case txCHR :
|
||||
constantChrFunc();
|
||||
break;
|
||||
|
||||
/* Function returning integer with scalar arguments */
|
||||
|
||||
case txORD :
|
||||
constantOrdFunc();
|
||||
break;
|
||||
|
||||
/* Functions returning BOOLEAN */
|
||||
case txODD :
|
||||
constantOddFunc();
|
||||
break;
|
||||
|
||||
/* Functions returning REAL with REAL/INTEGER arguments */
|
||||
|
||||
case txSQRT :
|
||||
constantRealFunc(fpSQRT);
|
||||
break;
|
||||
case txSIN :
|
||||
constantRealFunc(fpSIN);
|
||||
break;
|
||||
case txCOS :
|
||||
constantRealFunc(fpCOS);
|
||||
break;
|
||||
case txARCTAN :
|
||||
constantRealFunc(fpATAN);
|
||||
break;
|
||||
case txLN :
|
||||
constantRealFunc(fpLN);
|
||||
break;
|
||||
case txEXP :
|
||||
constantRealFunc(fpEXP);
|
||||
break;
|
||||
|
||||
case txGETENV : /* Non-standard C library interfaces */
|
||||
case txEOLN :
|
||||
case txEOF :
|
||||
default :
|
||||
error(eINVALIDPROC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static void constantAbsFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantAbsFunc]");
|
||||
|
||||
/* FORM: ABS (<simple integer/real expression>) */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
|
||||
if (constantToken == tINT_CONST)
|
||||
{
|
||||
if (constantInt < 0)
|
||||
constantInt = -constantInt;
|
||||
}
|
||||
else if (constantToken == tREAL_CONST)
|
||||
{
|
||||
if (constantReal < 0)
|
||||
constantReal = -constantInt;
|
||||
}
|
||||
else
|
||||
error(eINVARG);
|
||||
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static void constantOrdFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantOrdFunc]");
|
||||
|
||||
/* FORM: ORD (<scalar type>) */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
isOrdinalConstant();
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static void constantPredFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantPredFunc]");
|
||||
|
||||
/* FORM: PRED (<simple integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
isOrdinalConstant();
|
||||
constantInt--;
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static void constantSqrFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantSqrFunc]");
|
||||
|
||||
/* FORM: SQR (<simple integer OR real expression>) */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
if (constantToken == tINT_CONST)
|
||||
{
|
||||
constantInt *= constantInt;
|
||||
}
|
||||
else if (constantToken == tREAL_CONST)
|
||||
{
|
||||
constantReal *= constantReal;
|
||||
}
|
||||
else
|
||||
{
|
||||
error(eINVARG);
|
||||
}
|
||||
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static void constantRealFunc(uint8_t fpOpCode)
|
||||
{
|
||||
TRACE(lstFile,"[constantRealFunc]");
|
||||
|
||||
/* FORM: <function identifier> (<real/integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
if (constantToken == tINT_CONST)
|
||||
constantReal = (double)constantInt;
|
||||
else
|
||||
error(eINVARG);
|
||||
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static void constantSuccFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantSuccFunc]");
|
||||
|
||||
/* FORM: SUCC (<simple integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
isOrdinalConstant();
|
||||
constantInt++;
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void constantOddFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantOddFunc]");
|
||||
|
||||
/* FORM: ODD (<simple integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
isOrdinalConstant();
|
||||
constantInt &= 1;
|
||||
expression(exprAnyOrdinal, NULL);
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Process the standard chr function */
|
||||
|
||||
static void constantChrFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[constantCharFunc]");
|
||||
|
||||
/* Form: chr(integer expression).
|
||||
*
|
||||
* char(val) is only defined if there exists a character ch such
|
||||
* that ord(ch) = val. If this is not the case, we will simply
|
||||
* let the returned value exceed the range of type char. */
|
||||
|
||||
checkLParen();
|
||||
constantExpression();
|
||||
if (constantToken == tINT_CONST)
|
||||
{
|
||||
constantToken = tCHAR_CONST;
|
||||
}
|
||||
else
|
||||
{
|
||||
error(eINVARG);
|
||||
}
|
||||
|
||||
checkRParen();
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void constantReal2IntFunc(int kind)
|
||||
{
|
||||
error(eNOTYET);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void isOrdinalConstant(void)
|
||||
{
|
||||
if ((constantToken == tINT_CONST) || /* integer value */
|
||||
(constantToken == tCHAR_CONST) || /* character value */
|
||||
(constantToken == tBOOLEAN_CONST))
|
||||
return;
|
||||
else
|
||||
error(eINVARG);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/**********************************************************************
|
||||
* perr.c
|
||||
* Error Handlers
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Included Files
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "pedefs.h"
|
||||
|
||||
#include "pas.h"
|
||||
#include "ptkn.h"
|
||||
#include "perr.h"
|
||||
#if CONFIG_DEBUG
|
||||
# include "ptbl.h"
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
* Pre-processor Definitions
|
||||
**********************************************************************/
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
#define DUMPTABLES dumpTables()
|
||||
#else
|
||||
#define DUMPTABLES
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
* Private Variables
|
||||
**********************************************************************/
|
||||
|
||||
static const char fmtErrNoToken[] =
|
||||
"Line %d:%04ld Error %02x Token %02x\n";
|
||||
static const char fmtErrWithToken[] =
|
||||
"Line %d:%04ld Error %02x Token %02x (%s)\n";
|
||||
static const char fmtErrAbort[] =
|
||||
"Fatal Error %d -- Compilation aborted\n";
|
||||
|
||||
/**********************************************************************
|
||||
* Private Function Prototypes
|
||||
**********************************************************************/
|
||||
|
||||
static void printError(uint16_t errcode);
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void errmsg(char *fmt, ...)
|
||||
{
|
||||
char buffer[1024];
|
||||
va_list ap;
|
||||
|
||||
/* Get the full string */
|
||||
|
||||
va_start(ap, fmt);
|
||||
(void)vsprintf(buffer, fmt, ap);
|
||||
|
||||
/* Then output the string to stderr, the err file, and the list file */
|
||||
|
||||
fputs(buffer, stderr);
|
||||
fputs(buffer, errFile);
|
||||
fputs(buffer, lstFile);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void warn(uint16_t errcode)
|
||||
{
|
||||
TRACE(lstFile,"[warn:%04x]", errcode);
|
||||
|
||||
/* Write error record to the error and list files */
|
||||
|
||||
printError(errcode);
|
||||
|
||||
/* Increment the count of warning */
|
||||
|
||||
warn_count++;
|
||||
} /* end warn */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void error(uint16_t errcode)
|
||||
{
|
||||
TRACE(lstFile,"[error:%04x]", errcode);
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
fatal(errcode);
|
||||
#else
|
||||
/* Write error record to the error and list files */
|
||||
|
||||
printError(errcode);
|
||||
|
||||
/* Check if err_count has been execeeded the max allowable */
|
||||
|
||||
if ((++err_count) > MAX_ERRORS)
|
||||
{
|
||||
fatal(eCOUNT);
|
||||
}
|
||||
#endif
|
||||
|
||||
} /* end error */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void fatal(uint16_t errcode)
|
||||
{
|
||||
TRACE(lstFile,"[fatal:%04x]", errcode);
|
||||
|
||||
/* Write error record to the error and list files */
|
||||
|
||||
printError( errcode );
|
||||
|
||||
/* Dump the tables (if CONFIG_DEBUG) */
|
||||
|
||||
DUMPTABLES;
|
||||
|
||||
/* And say goodbye */
|
||||
|
||||
printf(fmtErrAbort, errcode);
|
||||
fprintf(lstFile, fmtErrAbort, errcode);
|
||||
|
||||
exit(1);
|
||||
|
||||
} /* end fatal */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void printError(uint16_t errcode)
|
||||
{
|
||||
/* Write error record to the error and list files */
|
||||
|
||||
if ((tkn_strt) && (tkn_strt < stringSP))
|
||||
{
|
||||
fprintf (errFile, fmtErrWithToken,
|
||||
FP->include, FP->line, errcode, token, tkn_strt);
|
||||
fprintf (lstFile, fmtErrWithToken,
|
||||
FP->include, FP->line, errcode, token, tkn_strt);
|
||||
stringSP = tkn_strt; /* Clean up string stack */
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
fprintf (errFile, fmtErrNoToken,
|
||||
FP->include, FP->line, errcode, token);
|
||||
fprintf (lstFile, fmtErrNoToken,
|
||||
FP->include, FP->line, errcode, token);
|
||||
} /* end else */
|
||||
} /* end printError */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,98 @@
|
||||
/***********************************************************************
|
||||
* pexpr.h
|
||||
* External Declarations associated with pexpr.c
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __PEXPR_H
|
||||
#define __PEXPR_H
|
||||
|
||||
/***********************************************************************
|
||||
* Included Files
|
||||
***********************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/***********************************************************************
|
||||
* Type Definitions
|
||||
***********************************************************************/
|
||||
|
||||
typedef enum exprEnum
|
||||
{
|
||||
exprUnknown = 0, /* TOS value unknown */
|
||||
exprAnyOrdinal, /* TOS = any ordinal type */
|
||||
exprAnyString, /* TOS = any string type */
|
||||
|
||||
exprInteger, /* TOS = integer value */
|
||||
exprReal, /* TOS = real value */
|
||||
exprChar, /* TOS = character value */
|
||||
exprBoolean, /* TOS = boolean(integer) value */
|
||||
exprScalar, /* TOS = scalar(integer) value */
|
||||
exprString, /* TOS = variable length string reference */
|
||||
exprStkString, /* TOS = reference to string on string stack */
|
||||
exprCString, /* TOS = pointer to C string */
|
||||
exprSet, /* TOS = set(integer) value */
|
||||
exprArray, /* TOS = array */
|
||||
exprRecord, /* TOS = record */
|
||||
|
||||
exprIntegerPtr, /* TOS = pointer to integer value */
|
||||
exprRealPtr, /* TOS = pointer to a real value */
|
||||
exprCharPtr, /* TOS = pointer to a character value */
|
||||
exprBooleanPtr, /* TOS = pointer to a boolean value */
|
||||
exprScalarPtr, /* TOS = pointer to a scalar value */
|
||||
exprSetPtr, /* TOS = pointer to a set value */
|
||||
exprArrayPtr, /* TOS = pointer to an array */
|
||||
exprRecordPtr /* TOS = pointer to a record */
|
||||
} exprType;
|
||||
|
||||
/***********************************************************************
|
||||
* Global Variables
|
||||
***********************************************************************/
|
||||
|
||||
extern int constantToken;
|
||||
extern int32_t constantInt;
|
||||
extern double constantReal;
|
||||
extern char *constantStart;
|
||||
|
||||
/***********************************************************************
|
||||
* Global Function Protypes
|
||||
***********************************************************************/
|
||||
|
||||
extern exprType expression ( exprType findExprType, STYPE *typePtr );
|
||||
extern exprType varParm ( exprType varExprType, STYPE *typePtr );
|
||||
extern void arrayIndex ( int32_t size );
|
||||
extern exprType getExprType( STYPE *sType );
|
||||
|
||||
extern void constantExpression(void);
|
||||
|
||||
#endif /* __PEXPR_H */
|
||||
@@ -0,0 +1,452 @@
|
||||
/***************************************************************
|
||||
* pfunc.c
|
||||
* Standard Functions
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* Included Files
|
||||
***************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "podefs.h"
|
||||
#include "pfdefs.h"
|
||||
#include "pedefs.h"
|
||||
#include "pxdefs.h"
|
||||
|
||||
#include "pas.h"
|
||||
#include "pexpr.h"
|
||||
#include "pfunc.h"
|
||||
#include "pgen.h" /* for pas_Generate*() */
|
||||
#include "ptkn.h"
|
||||
#include "pinsn.h"
|
||||
#include "perr.h"
|
||||
|
||||
/***************************************************************
|
||||
* Private Function Prototypes
|
||||
***************************************************************/
|
||||
|
||||
/* Standard Pascal Functions */
|
||||
|
||||
static exprType absFunc (void); /* Integer absolute value */
|
||||
static exprType predFunc (void);
|
||||
static void ordFunc (void); /* Convert scalar to integer */
|
||||
static exprType sqrFunc (void);
|
||||
static void realFunc (uint8_t fpCode);
|
||||
static exprType succFunc (void);
|
||||
static void oddFunc (void);
|
||||
static void chrFunc (void);
|
||||
static void fileFunc (uint16_t opcode);
|
||||
|
||||
/* Enhanced Pascal functions */
|
||||
|
||||
/* Non-standard C-library interface functions */
|
||||
|
||||
static exprType getenvFunc (void); /* Get environment string value */
|
||||
|
||||
/***************************************************************
|
||||
* Public Functions
|
||||
***************************************************************/
|
||||
|
||||
void primeBuiltInFunctions(void)
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* Process a standard Pascal function call */
|
||||
|
||||
exprType builtInFunction(void)
|
||||
{
|
||||
exprType funcType = exprUnknown;
|
||||
|
||||
TRACE(lstFile,"[builtInFunction]");
|
||||
|
||||
/* Is the token a function? */
|
||||
|
||||
if (token == tFUNC)
|
||||
{
|
||||
/* Yes, process it procedure according to the extended token type */
|
||||
|
||||
switch (tknSubType)
|
||||
{
|
||||
/* Functions which return the same type as their argument */
|
||||
case txABS :
|
||||
funcType = absFunc();
|
||||
break;
|
||||
case txSQR :
|
||||
funcType = sqrFunc();
|
||||
break;
|
||||
case txPRED :
|
||||
funcType = predFunc();
|
||||
break;
|
||||
case txSUCC :
|
||||
funcType = succFunc();
|
||||
break;
|
||||
|
||||
case txGETENV : /* Non-standard C library interfaces */
|
||||
funcType = getenvFunc();
|
||||
break;
|
||||
|
||||
/* Functions returning INTEGER with REAL arguments */
|
||||
|
||||
case txROUND :
|
||||
getToken(); /* Skip over 'round' */
|
||||
expression(exprReal, NULL);
|
||||
pas_GenerateFpOperation(fpROUND);
|
||||
funcType = exprInteger;
|
||||
break;
|
||||
case txTRUNC :
|
||||
getToken(); /* Skip over 'trunc' */
|
||||
expression(exprReal, NULL);
|
||||
pas_GenerateFpOperation(fpTRUNC);
|
||||
funcType = exprInteger;
|
||||
break;
|
||||
|
||||
/* Functions returning CHARACTER with INTEGER arguments. */
|
||||
|
||||
case txCHR :
|
||||
chrFunc();
|
||||
funcType = exprChar;
|
||||
break;
|
||||
|
||||
/* Function returning integer with scalar arguments */
|
||||
|
||||
case txORD :
|
||||
ordFunc();
|
||||
funcType = exprInteger;
|
||||
break;
|
||||
|
||||
/* Functions returning BOOLEAN */
|
||||
case txODD :
|
||||
oddFunc();
|
||||
funcType = exprBoolean;
|
||||
break;
|
||||
case txEOF :
|
||||
fileFunc(xEOF);
|
||||
funcType = exprBoolean;
|
||||
break;
|
||||
case txEOLN :
|
||||
fileFunc(xEOLN);
|
||||
funcType = exprBoolean;
|
||||
break;
|
||||
|
||||
/* Functions returning REAL with REAL/INTEGER arguments */
|
||||
|
||||
case txSQRT :
|
||||
realFunc(fpSQRT);
|
||||
funcType = exprReal;
|
||||
break;
|
||||
case txSIN :
|
||||
realFunc(fpSIN);
|
||||
funcType = exprReal;
|
||||
break;
|
||||
case txCOS :
|
||||
realFunc(fpCOS);
|
||||
funcType = exprReal;
|
||||
break;
|
||||
case txARCTAN :
|
||||
realFunc(fpATAN);
|
||||
funcType = exprReal;
|
||||
break;
|
||||
case txLN :
|
||||
realFunc(fpLN);
|
||||
funcType = exprReal;
|
||||
break;
|
||||
case txEXP :
|
||||
realFunc(fpEXP);
|
||||
funcType = exprReal;
|
||||
break;
|
||||
|
||||
default :
|
||||
error(eINVALIDPROC);
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end if */
|
||||
|
||||
return funcType;
|
||||
|
||||
} /* end builtInFunction */
|
||||
|
||||
void checkLParen(void)
|
||||
{
|
||||
getToken(); /* Skip over function name */
|
||||
if (token != '(') error(eLPAREN); /* Check for '(' */
|
||||
else getToken();
|
||||
}
|
||||
|
||||
void checkRParen(void)
|
||||
{
|
||||
if (token != ')') error(eRPAREN); /* Check for ')') */
|
||||
else getToken();
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Private Functions
|
||||
***************************************************************/
|
||||
|
||||
static exprType absFunc(void)
|
||||
{
|
||||
exprType absType;
|
||||
|
||||
TRACE(lstFile,"[absFunc]");
|
||||
|
||||
/* FORM: ABS (<simple integer/real expression>) */
|
||||
|
||||
checkLParen();
|
||||
|
||||
absType = expression(exprUnknown, NULL);
|
||||
if (absType == exprInteger)
|
||||
pas_GenerateSimple(opABS);
|
||||
else if (absType == exprReal)
|
||||
pas_GenerateFpOperation(fpABS);
|
||||
else
|
||||
error(eINVARG);
|
||||
|
||||
checkRParen();
|
||||
return absType;
|
||||
|
||||
} /* end absFunc */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static void ordFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[ordFunc]");
|
||||
|
||||
/* FORM: ORD (<scalar type>) */
|
||||
|
||||
checkLParen();
|
||||
expression(exprAnyOrdinal, NULL); /* Get any ordinal type */
|
||||
checkRParen();
|
||||
|
||||
} /* end ordFunc */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static exprType predFunc(void)
|
||||
{
|
||||
exprType predType;
|
||||
|
||||
TRACE(lstFile,"[predFunc]");
|
||||
|
||||
/* FORM: PRED (<simple integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
|
||||
/* Process any ordinal expression */
|
||||
|
||||
predType = expression(exprAnyOrdinal, NULL);
|
||||
checkRParen();
|
||||
pas_GenerateSimple(opDEC);
|
||||
return predType;
|
||||
|
||||
} /* end predFunc */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static exprType sqrFunc(void)
|
||||
{
|
||||
exprType sqrType;
|
||||
|
||||
TRACE(lstFile,"[sqrFunc]");
|
||||
|
||||
/* FORM: SQR (<simple integer OR real expression>) */
|
||||
|
||||
checkLParen();
|
||||
|
||||
sqrType = expression(exprUnknown, NULL); /* Process any expression */
|
||||
if (sqrType == exprInteger) {
|
||||
|
||||
pas_GenerateSimple(opDUP);
|
||||
pas_GenerateSimple(opMUL);
|
||||
|
||||
} /* end if */
|
||||
else if (sqrType == exprReal)
|
||||
pas_GenerateFpOperation(fpSQR);
|
||||
|
||||
else
|
||||
error(eINVARG);
|
||||
|
||||
checkRParen();
|
||||
return sqrType;
|
||||
|
||||
} /* end sqrFunc */
|
||||
|
||||
/**********************************************************************/
|
||||
static void realFunc (uint8_t fpOpCode)
|
||||
{
|
||||
exprType realType;
|
||||
|
||||
TRACE(lstFile,"[realFunc]");
|
||||
|
||||
/* FORM: <function identifier> (<real/integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
|
||||
realType = expression(exprUnknown, NULL); /* Process any expression */
|
||||
if (realType == exprInteger)
|
||||
pas_GenerateFpOperation((fpOpCode | fpARG1));
|
||||
else if (realType == exprReal)
|
||||
pas_GenerateFpOperation(fpOpCode);
|
||||
else
|
||||
error(eINVARG);
|
||||
|
||||
checkRParen();
|
||||
|
||||
} /* end realFunc */
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
static exprType succFunc(void)
|
||||
{
|
||||
exprType succType;
|
||||
|
||||
TRACE(lstFile,"[succFunc]");
|
||||
|
||||
/* FORM: SUCC (<simple integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
|
||||
/* Process any ordinal expression */
|
||||
|
||||
succType = expression(exprAnyOrdinal, NULL);
|
||||
|
||||
checkRParen();
|
||||
pas_GenerateSimple(opINC);
|
||||
return succType;
|
||||
|
||||
} /* end succFunc */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void oddFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[oddFunc]");
|
||||
|
||||
/* FORM: ODD (<simple integer expression>) */
|
||||
|
||||
checkLParen();
|
||||
|
||||
/* Process any ordinal expression */
|
||||
|
||||
expression(exprAnyOrdinal, NULL);
|
||||
checkRParen();
|
||||
pas_GenerateDataOperation(opPUSH, 1);
|
||||
pas_GenerateSimple(opAND);
|
||||
pas_GenerateSimple(opNEQZ);
|
||||
|
||||
} /* end oddFunc */
|
||||
|
||||
/***********************************************************************/
|
||||
/* Process the standard chr function */
|
||||
|
||||
static void chrFunc(void)
|
||||
{
|
||||
TRACE(lstFile,"[charFactor]");
|
||||
|
||||
/* Form: chr(integer expression).
|
||||
*
|
||||
* char(val) is only defined if there exists a character ch such
|
||||
* that ord(ch) = val. If this is not the case, we will simply
|
||||
* let the returned value exceed the range of type char. */
|
||||
|
||||
checkLParen();
|
||||
expression(exprInteger, NULL);
|
||||
checkRParen();
|
||||
|
||||
} /* end chrFunc */
|
||||
|
||||
/****************************************************************************/
|
||||
/* EOF/EOLN function */
|
||||
|
||||
static void fileFunc(uint16_t opcode)
|
||||
{
|
||||
TRACE(lstFile,"[fileFunc]");
|
||||
|
||||
/* FORM: EOF|EOLN (<file number>) */
|
||||
|
||||
checkLParen();
|
||||
if (token != sFILE)
|
||||
{
|
||||
error(eFILE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pas_GenerateDataOperation(opINDS, sBOOLEAN_SIZE);
|
||||
pas_GenerateIoOperation(opcode, tknPtr->sParm.fileNumber);
|
||||
getToken();
|
||||
checkRParen();
|
||||
} /* end else */
|
||||
|
||||
} /* end fileFunc */
|
||||
|
||||
/**********************************************************************/
|
||||
/* C library getenv interface */
|
||||
|
||||
static exprType getenvFunc(void)
|
||||
{
|
||||
exprType stringType;
|
||||
|
||||
TRACE(lstFile, "[getenvFunc]");
|
||||
|
||||
/* FORM: <string_var> = getenv(<string>) */
|
||||
|
||||
checkLParen();
|
||||
|
||||
/* Get the string expression representing the environment variable
|
||||
* name.
|
||||
*/
|
||||
|
||||
stringType = expression(exprString, NULL);
|
||||
|
||||
/* Two possible kinds of strings could be returned.
|
||||
* Anything else other then 'exprString' would be an error (but
|
||||
* should happen).
|
||||
*/
|
||||
|
||||
if ((stringType != exprString) && (stringType != exprStkString))
|
||||
{
|
||||
error(eINVARG);
|
||||
}
|
||||
|
||||
pas_BuiltInFunctionCall(lbGETENV);
|
||||
checkRParen();
|
||||
return exprCString;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
* pfunc.h
|
||||
* External Declarations associated with pfunc.c
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PFUNC_H
|
||||
#define __PFUNC_H
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include "pexpr.h" /* For exprType */
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void primeBuiltInFunctions(void);
|
||||
extern exprType builtInFunction(void);
|
||||
extern void builtInFunctionOfConstant(void);
|
||||
|
||||
extern void checkLParen(void);
|
||||
extern void checkRParen(void);
|
||||
|
||||
#endif /* __PFUNC_H */
|
||||
@@ -0,0 +1,641 @@
|
||||
/**********************************************************************
|
||||
* pgen.c
|
||||
* P-Code generation logic
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Included Files
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "config.h" /* Configuration */
|
||||
#include "keywords.h" /* Standard types */
|
||||
#include "pasdefs.h" /* Common types */
|
||||
#include "ptdefs.h" /* Token / symbol table definitions */
|
||||
#include "podefs.h" /* Logical opcode definitions */
|
||||
#include "pedefs.h" /* error code definitions */
|
||||
|
||||
#include "pas.h" /* Global variables */
|
||||
#include "poff.h" /* For POFF file format */
|
||||
#include "pofflib.h" /* For poff*() functions*/
|
||||
#include "pinsn.h" /* (DEBUG only) */
|
||||
#include "perr.h" /* error() */
|
||||
|
||||
#include "pproc.h" /* for actualParameterSize */
|
||||
#include "pgen.h" /* (to verify prototypes in this file) */
|
||||
|
||||
/**********************************************************************
|
||||
* Pre-processor Definitions
|
||||
**********************************************************************/
|
||||
|
||||
#define UNDEFINED_LEVEL (-1)
|
||||
#define INVALID_PCODE (-1)
|
||||
|
||||
#define LEVEL_DEFINED(l) ((int32_t)(l) >= 0)
|
||||
#define PCODE_VALID(p) ((int32_t)(p) >= 0)
|
||||
|
||||
/**********************************************************************
|
||||
* Global Variables
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Private Variables
|
||||
**********************************************************************/
|
||||
|
||||
static int32_t g_currentStackLevelReference = UNDEFINED_LEVEL;
|
||||
static uint32_t g_nStackLevelReferenceChanges = 0;
|
||||
|
||||
/***********************************************************************
|
||||
* Private Function Prototypes
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Private Functions
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate a stack reference opcode to a global variable residing at
|
||||
* static nesting level zero.
|
||||
*/
|
||||
|
||||
static void
|
||||
pas_GenerateLevel0StackReference(enum pcode_e eOpCode, STYPE *pVar)
|
||||
{
|
||||
/* Sanity checking. Double check nesting level and also since this is
|
||||
* a level zero reference, then the offset must be positive
|
||||
*/
|
||||
|
||||
if ((pVar->sLevel != 0) || (pVar->sParm.v.offset < 0))
|
||||
{
|
||||
error(eHUH);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Generate the P-code */
|
||||
|
||||
insn_GenerateDataOperation(eOpCode, pVar->sParm.v.offset);
|
||||
|
||||
/* If the variable is undefined, also generate a relocation
|
||||
* record.
|
||||
*/
|
||||
|
||||
if ((pVar->sParm.v.flags & SVAR_EXTERNAL) != 0)
|
||||
{
|
||||
(void)poffAddRelocation(poffHandle, RLT_LDST,
|
||||
pVar->sParm.v.symIndex, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* There are some special P-codes for accessing stack data at static
|
||||
* nesting level 0. Check if the specified opcode is one of those. If
|
||||
* so, return the mapped opcode. Otherwise, return INVALID_PCODE.
|
||||
*/
|
||||
|
||||
static int32_t
|
||||
pas_GetLevel0Opcode(enum pcode_e eOpCode)
|
||||
{
|
||||
switch (eOpCode)
|
||||
{
|
||||
case opLDS: return opLD;
|
||||
case opLDSH: return opLDH;
|
||||
case opLDSB: return opLDB;
|
||||
case opLDSM: return opLDM;
|
||||
case opSTS: return opST;
|
||||
case opSTSB: return opSTB;
|
||||
case opSTSM: return opSTM;
|
||||
case opLDSX: return opLDX;
|
||||
case opLDSXB: return opLDXB;
|
||||
case opLDSXM: return opLDXM;
|
||||
case opSTSX: return opSTX;
|
||||
case opSTSXB: return opSTXB;
|
||||
case opSTSXM: return opSTXM;
|
||||
case opLAS: return opLA;
|
||||
case opLASX: return opLAX;
|
||||
default: return INVALID_PCODE;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* A new static nesting level has been encountered. Check if we need
|
||||
* to reset the level stack pointer (LSP) register (assuming that the
|
||||
* architecutre has one).
|
||||
*/
|
||||
|
||||
static void
|
||||
pas_SetLevelStackPointer(uint32_t dwLevel)
|
||||
{
|
||||
if (dwLevel != g_currentStackLevelReference)
|
||||
{
|
||||
/* Set the level stack pointer (LSP) register */
|
||||
|
||||
insn_SetStackLevel(dwLevel);
|
||||
|
||||
/* Remember the setting so that we do not reset the LSP until
|
||||
* the level changes (or it is invalidated).
|
||||
*/
|
||||
|
||||
g_currentStackLevelReference = dwLevel;
|
||||
g_nStackLevelReferenceChanges++;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Public Functions
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************/
|
||||
/* Return the current setting of the level stack pointer (LSP) register
|
||||
* -- assuming that the underlying architecure may have one.
|
||||
*/
|
||||
|
||||
int32_t pas_GetCurrentStackLevel(void)
|
||||
{
|
||||
return g_currentStackLevelReference;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Invalidate the current stack level register setting. This will cause
|
||||
* us to reset the LSP when the next stack level reference is encountered.
|
||||
*/
|
||||
|
||||
void pas_InvalidateCurrentStackLevel(void)
|
||||
{
|
||||
g_currentStackLevelReference = UNDEFINED_LEVEL;
|
||||
g_nStackLevelReferenceChanges++;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Set the stack level pointer to known value. This is done when in
|
||||
* while and for loop processing. The value of the LSP will be that
|
||||
* as sampled at the top of the lop not necessarily the value at the
|
||||
* bottom of the loop.
|
||||
*/
|
||||
|
||||
void pas_SetCurrentStackLevel(int32_t dwLsp)
|
||||
{
|
||||
g_currentStackLevelReference = dwLsp;
|
||||
g_nStackLevelReferenceChanges++;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Get the number of changes made to the level stack pointer. This is
|
||||
* useful by compiler logic to determine if the stack level pointer was
|
||||
* ever changed by any logic path.
|
||||
*/
|
||||
|
||||
uint32_t pas_GetNStackLevelChanges(void)
|
||||
{
|
||||
return g_nStackLevelReferenceChanges;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate the most simple of all P-codes */
|
||||
|
||||
void pas_GenerateSimple(enum pcode_e eOpCode)
|
||||
{
|
||||
insn_GenerateSimple(eOpCode);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate a P-code with a single data argument */
|
||||
|
||||
void pas_GenerateDataOperation(enum pcode_e eOpCode, int32_t dwData)
|
||||
{
|
||||
insn_GenerateDataOperation(eOpCode, dwData);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* This function is called just before a multiple register operation is
|
||||
* is generated. This should generate logic to specify the size of the
|
||||
* multiple register operation (in bytes, not registers). This may translate
|
||||
* into different operations on different architectures. Typically,
|
||||
* this would generate a push of the size onto the stack or, perhaps,
|
||||
* setting of a dedicated count register.
|
||||
*/
|
||||
|
||||
void pas_GenerateDataSize(int32_t dwDataSize)
|
||||
{
|
||||
insn_GenerateDataSize(dwDataSize);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate a floating point operation */
|
||||
|
||||
void pas_GenerateFpOperation(uint8_t fpOpcode)
|
||||
{
|
||||
insn_GenerateFpOperation(fpOpcode);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate an IO operation */
|
||||
|
||||
void pas_GenerateIoOperation(uint16_t ioOpcode, uint16_t fileNumber)
|
||||
{
|
||||
insn_GenerateIoOperation(ioOpcode, fileNumber);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate a pseudo call to a built-in, standard pascal function */
|
||||
|
||||
void pas_BuiltInFunctionCall(uint16_t libOpcode)
|
||||
{
|
||||
insn_BuiltInFunctionCall(libOpcode);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate a reference to data on the data stack using the specified
|
||||
* level and offset.
|
||||
*/
|
||||
|
||||
void pas_GenerateLevelReference(enum pcode_e eOpCode, uint16_t wLevel,
|
||||
int32_t dwOffset)
|
||||
{
|
||||
/* Is this variable declared at level 0 (i.e., it has global scope)
|
||||
* that is being offset via a nesting level?
|
||||
*/
|
||||
|
||||
if (wLevel == 0)
|
||||
{
|
||||
int32_t level0Opcode = pas_GetLevel0Opcode(eOpCode);
|
||||
if (PCODE_VALID(level0Opcode))
|
||||
{
|
||||
insn_GenerateDataOperation(level0Opcode, dwOffset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* We get here if the reference is at some static nesting level
|
||||
* other that zero OR if there is no special PCode to reference
|
||||
* data at static nesting level 0 for this operation.
|
||||
*
|
||||
* Check if we have to change the level stack pointer (LSP) register
|
||||
* (assuming that the architecture has one).
|
||||
*/
|
||||
|
||||
pas_SetLevelStackPointer(wLevel);
|
||||
|
||||
/* Then generate the opcode passing the level in the event that the
|
||||
* architecture does not have an LSP.
|
||||
*/
|
||||
|
||||
insn_GenerateLevelReference(eOpCode, wLevel, dwOffset);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate a stack reference opcode, handling references to undefined
|
||||
* stack offsets.
|
||||
*/
|
||||
|
||||
void pas_GenerateStackReference(enum pcode_e eOpCode, STYPE *pVar)
|
||||
{
|
||||
/* Is this variable declared at level 0 (i.e., it has global scope)
|
||||
* that is being offset via a nesting level?
|
||||
*/
|
||||
|
||||
if (pVar->sLevel == 0)
|
||||
{
|
||||
int32_t level0Opcode = pas_GetLevel0Opcode(eOpCode);
|
||||
if (PCODE_VALID(level0Opcode))
|
||||
{
|
||||
pas_GenerateLevel0StackReference(level0Opcode, pVar);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* We get here if the reference is at some static nesting level
|
||||
* other that zero OR if there is no special PCode to reference
|
||||
* data at static nesting level 0 for this operation.
|
||||
*
|
||||
* Check if we have to change the level stack pointer (LSP) register
|
||||
* (assuming that the architecture has one).
|
||||
*/
|
||||
|
||||
pas_SetLevelStackPointer(pVar->sLevel);
|
||||
|
||||
/* Generate the P-Code at the defined offset and with the specified
|
||||
* static level offset (in case that the architecture does not have
|
||||
* an LSP)
|
||||
*/
|
||||
|
||||
insn_GenerateLevelReference(eOpCode, (level - pVar->sLevel),
|
||||
pVar->sParm.v.offset);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate a procedure call and an associated relocation record if the
|
||||
* called procedure is external.
|
||||
*/
|
||||
|
||||
void
|
||||
pas_GenerateProcedureCall(STYPE *pProc)
|
||||
{
|
||||
/* sLevel is the level at which the procedure was declared. We need
|
||||
* to set the SLP to this value prior to the call (on some architectures
|
||||
* where the SLP is pushed onto the stack by the procedure
|
||||
* call).
|
||||
*/
|
||||
|
||||
pas_SetLevelStackPointer(pProc->sLevel);
|
||||
|
||||
/* Then generate the procedure call (passing the level again for those
|
||||
* architectures that do not support the SLP.
|
||||
*/
|
||||
|
||||
insn_GenerateProcedureCall(pProc->sLevel, pProc->sParm.p.label);
|
||||
|
||||
/* If the variable is undefined, also generate a relocation
|
||||
* record.
|
||||
*/
|
||||
|
||||
#if 0 /* Not yet */
|
||||
if ((pVar->sParm.p.flags & SVAR_EXTERNAL) != 0)
|
||||
{
|
||||
/* For now */
|
||||
# error "Don't know what last parameter should be"
|
||||
(void)poffAddRelocation(poffHandle, RLT_PCAL,
|
||||
pVar->sParm.p.symIndex,
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Any logic after the procedure/function call return must assume
|
||||
* that the last level reference is unknown.
|
||||
*/
|
||||
|
||||
pas_InvalidateCurrentStackLevel();
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void pas_GenerateLineNumber(uint16_t wIncludeNumber, uint32_t dwLineNumber)
|
||||
{
|
||||
insn_GenerateLineNumber(wIncludeNumber, dwLineNumber);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void pas_GenerateDebugInfo(STYPE *pProc, uint32_t dwReturnSize)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Allocate a container to pass the proc information to the library */
|
||||
|
||||
uint32_t nparms = pProc->sParm.p.nParms;
|
||||
poffLibDebugFuncInfo_t *pContainer = poffCreateDebugInfoContainer(nparms);
|
||||
|
||||
/* Put the proc information into the container */
|
||||
|
||||
pContainer->value = pProc->sParm.p.label;
|
||||
pContainer->retsize = dwReturnSize;
|
||||
pContainer->nparms = nparms;
|
||||
|
||||
/* Add the argument information to the container */
|
||||
|
||||
for (i = 0; i < nparms; i++)
|
||||
{
|
||||
pContainer->argsize[i] = actualParameterSize(pProc, i+1);
|
||||
}
|
||||
|
||||
/* Add the contained information to the library */
|
||||
|
||||
poffAddDebugFuncInfo(poffHandle, pContainer);
|
||||
|
||||
/* Release the container */
|
||||
|
||||
poffReleaseDebugFuncContainer(pContainer);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate description of a level 0 stack variable that can be
|
||||
* exported by a unit.
|
||||
*/
|
||||
|
||||
void pas_GenerateStackExport(STYPE *pVar)
|
||||
{
|
||||
poffLibSymbol_t symbol;
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
/* Get the parent type of the variable */
|
||||
|
||||
STYPE *typePtr = pVar->sParm.v.parent;
|
||||
|
||||
/* Perform some sanity checking:
|
||||
* - Must have a parent type
|
||||
* - Must not be declared external
|
||||
* - Must be declared at static nesting level zero
|
||||
*/
|
||||
|
||||
if ((!typePtr) ||
|
||||
((pVar->sParm.v.flags & SVAR_EXTERNAL) != 0) ||
|
||||
(pVar->sLevel != 0))
|
||||
{
|
||||
error(eSYMTABINTERNAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create the symbol structure */
|
||||
|
||||
symbol.type = STT_DATA;
|
||||
symbol.align = STA_8BIT; /* for now */
|
||||
symbol.flags = STF_NONE;
|
||||
symbol.name = pVar->sName;
|
||||
symbol.value = pVar->sParm.v.offset;
|
||||
symbol.size = pVar->sParm.v.size;
|
||||
|
||||
/* Add the symbol to the symbol table */
|
||||
|
||||
(void)poffAddSymbol(poffHandle, &symbol);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate description of a level 0 stack variable that must be
|
||||
* imported by a program or unit from a unit.
|
||||
*/
|
||||
|
||||
void pas_GenerateStackImport(STYPE *pVar)
|
||||
{
|
||||
poffLibSymbol_t symbol;
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
/* Get the parent type of the variable */
|
||||
|
||||
STYPE *typePtr = pVar->sParm.v.parent;
|
||||
|
||||
/* Perform some sanity checking
|
||||
* - Must have a parent type
|
||||
* - Must be declared external
|
||||
* - Must be declared at static nesting level zero
|
||||
*/
|
||||
|
||||
if ((!typePtr) ||
|
||||
((pVar->sParm.v.flags & SVAR_EXTERNAL) == 0) ||
|
||||
(pVar->sLevel != 0))
|
||||
{
|
||||
error(eSYMTABINTERNAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create the symbol structure */
|
||||
|
||||
symbol.type = STT_DATA;
|
||||
symbol.align = STA_8BIT; /* for now */
|
||||
symbol.flags = STF_UNDEFINED;
|
||||
symbol.name = pVar->sName;
|
||||
symbol.value = pVar->sParm.v.offset; /* for now */
|
||||
symbol.size = pVar->sParm.v.size;
|
||||
|
||||
/* Add the symbol to the symbol table */
|
||||
|
||||
pVar->sParm.v.symIndex = poffAddSymbol(poffHandle, &symbol);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate description of a level 0 procedure or function that can be
|
||||
* exported by a unit.
|
||||
*/
|
||||
|
||||
void pas_GenerateProcExport(STYPE *pProc)
|
||||
{
|
||||
poffLibSymbol_t symbol;
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
/* Get the parent type of the function (assuming it is a function) */
|
||||
|
||||
STYPE *typePtr = pProc->sParm.p.parent;
|
||||
|
||||
/* Perform some sanity checking */
|
||||
|
||||
/* Check for a function reference which must have a valid parent type */
|
||||
|
||||
if ((pProc->sKind == sFUNC) && (typePtr != NULL));
|
||||
|
||||
/* Check for a procedure reference which must not have a valid type */
|
||||
|
||||
else if ((pProc->sKind == sPROC) && (typePtr == NULL));
|
||||
|
||||
/* Anything else is an error */
|
||||
|
||||
else
|
||||
error(eSYMTABINTERNAL);
|
||||
|
||||
/* The function / procedure should NOT be declared external and
|
||||
* only procedures declared at static nesting level zero can
|
||||
* be exported.
|
||||
*/
|
||||
|
||||
if (((pProc->sParm.p.flags & SPROC_EXTERNAL) != 0) ||
|
||||
(pProc->sLevel != 0))
|
||||
error(eSYMTABINTERNAL);
|
||||
#endif
|
||||
|
||||
/* Everthing looks okay. Create the symbol structure */
|
||||
|
||||
if (pProc->sKind == sPROC)
|
||||
symbol.type = STT_PROC;
|
||||
else
|
||||
symbol.type = STT_FUNC;
|
||||
|
||||
symbol.align = STA_NONE;
|
||||
symbol.flags = STF_NONE;
|
||||
symbol.name = pProc->sName;
|
||||
symbol.value = pProc->sParm.p.label;
|
||||
symbol.size = 0;
|
||||
|
||||
/* Add the symbol to the symbol table */
|
||||
|
||||
(void)poffAddSymbol(poffHandle, &symbol);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* Generate description of a level 0 procedure or function that must be
|
||||
* imported by a program or unit from a unit.
|
||||
*/
|
||||
|
||||
void pas_GenerateProcImport(STYPE *pProc)
|
||||
{
|
||||
poffLibSymbol_t symbol;
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
/* Get the parent type of the function (assuming it is a function) */
|
||||
|
||||
STYPE *typePtr = pProc->sParm.p.parent;
|
||||
|
||||
/* Perform some sanity checking */
|
||||
|
||||
/* Check for a function reference which must have a valid parent type */
|
||||
|
||||
if ((pProc->sKind == sFUNC) && (typePtr != NULL));
|
||||
|
||||
/* Check for a procedure reference which must not have a valid type */
|
||||
|
||||
else if ((pProc->sKind == sPROC) && (typePtr == NULL));
|
||||
|
||||
/* Anything else is an error */
|
||||
|
||||
else
|
||||
error(eSYMTABINTERNAL);
|
||||
|
||||
/* The function / procedure should also be declared external and
|
||||
* only procedures declared at static nesting level zero can
|
||||
* be exported.
|
||||
*/
|
||||
|
||||
if (((pProc->sParm.p.flags & SPROC_EXTERNAL) == 0) ||
|
||||
(pProc->sLevel != 0))
|
||||
error(eSYMTABINTERNAL);
|
||||
#endif
|
||||
|
||||
/* Everthing looks okay. Create the symbol structure */
|
||||
|
||||
if (pProc->sKind == sPROC)
|
||||
symbol.type = STT_PROC;
|
||||
else
|
||||
symbol.type = STT_FUNC;
|
||||
|
||||
symbol.align = STA_NONE;
|
||||
symbol.flags = STF_UNDEFINED;
|
||||
symbol.name = pProc->sName;
|
||||
symbol.value = pProc->sParm.p.label;
|
||||
symbol.size = 0;
|
||||
|
||||
/* Add the symbol to the symbol table */
|
||||
|
||||
pProc->sParm.p.symIndex = poffAddSymbol(poffHandle, &symbol);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/***************************************************************************
|
||||
* pgen.h
|
||||
* External Declarations associated with pgen.c
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PGEN_H
|
||||
#define __PGEN_H
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "podefs.h"
|
||||
|
||||
/***************************************************************************
|
||||
* Pre-processor Definitions
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Global Types
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Global Variable Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern int32_t pas_GetCurrentStackLevel(void);
|
||||
extern void pas_InvalidateCurrentStackLevel(void);
|
||||
extern void pas_SetCurrentStackLevel(int32_t dwLsp);
|
||||
extern uint32_t pas_GetNStackLevelChanges(void);
|
||||
|
||||
extern void pas_GenerateSimple(enum pcode_e eOpCode);
|
||||
extern void pas_GenerateDataOperation(enum pcode_e eOpCode, int32_t dwData);
|
||||
extern void pas_GenerateDataSize(int32_t dwDataSize);
|
||||
extern void pas_GenerateFpOperation(uint8_t fpOpcode);
|
||||
extern void pas_GenerateIoOperation(uint16_t ioOpcode, uint16_t fileNumber);
|
||||
extern void pas_BuiltInFunctionCall(uint16_t libOpcode);
|
||||
extern void pas_GenerateLevelReference(enum pcode_e eOpCode, uint16_t wLevel,
|
||||
int32_t dwOffset);
|
||||
extern void pas_GenerateStackReference(enum pcode_e eOpCode, STYPE *pVarPtr);
|
||||
extern void pas_GenerateProcedureCall(STYPE *pProcPtr);
|
||||
extern void pas_GenerateLineNumber(uint16_t wIncludeNumber,
|
||||
uint32_t dwLineNumber);
|
||||
extern void pas_GenerateStackExport(STYPE *pVarPtr);
|
||||
extern void pas_GenerateStackImport(STYPE *pVarPtr);
|
||||
extern void pas_GenerateProcedureCall(STYPE *pProcPtr);
|
||||
extern void pas_GenerateDebugInfo(STYPE *pProcPtr, uint32_t dwReturnSize);
|
||||
extern void pas_GenerateProcExport(STYPE *pProcPtr);
|
||||
extern void pas_GenerateProcImport(STYPE *pProcPtr);
|
||||
extern void pas_GeneratePoffOutput(void);
|
||||
|
||||
#endif /* __PGEN_H */
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/**********************************************************************
|
||||
* pas.c
|
||||
* main - process PROGRAM
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Included Files
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "podefs.h"
|
||||
#include "pedefs.h"
|
||||
#include "poff.h" /* FHT_ definitions */
|
||||
|
||||
#include "pas.h" /* for globals + openNestedFile */
|
||||
#include "pblck.h" /* for block() */
|
||||
#include "pgen.h" /* for pas_Generate*() */
|
||||
#include "ptkn.h" /* for getToken() */
|
||||
#include "ptbl.h" /* for addFile() */
|
||||
#include "pofflib.h" /* For poff*() functions*/
|
||||
#include "paslib.h" /* for extension() */
|
||||
#include "perr.h" /* for error() */
|
||||
#include "punit.h" /* for unit() */
|
||||
#include "pprgm.h"
|
||||
|
||||
/**********************************************************************
|
||||
* Pre-processor Definitions
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Global Variables
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Private Variables
|
||||
**********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Private Function Prototypes
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Private Functions
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Public Functions
|
||||
***********************************************************************/
|
||||
|
||||
void program(void)
|
||||
{
|
||||
char *pgmname = NULL;
|
||||
|
||||
TRACE(lstFile, "[program]");
|
||||
|
||||
/* FORM: program = program-heading ';' [uses-section ] block '.'
|
||||
* FORM: program-heading = 'program' identifier [ '(' identifier-list ')' ]
|
||||
*
|
||||
* On entry, 'program' has already been identified and token refers to
|
||||
* the next token after 'program'
|
||||
*/
|
||||
|
||||
if (token != tIDENT) error(eIDENT); /* Verify <program name> */
|
||||
else
|
||||
{
|
||||
pgmname = tkn_strt; /* Save program name */
|
||||
getToken();
|
||||
} /* end else */
|
||||
|
||||
/* Process optional file list (allow re-declaration of INPUT & OUTPUT) */
|
||||
|
||||
if (token == '(')
|
||||
{
|
||||
do
|
||||
{
|
||||
getToken();
|
||||
if (token == tIDENT)
|
||||
{
|
||||
if ((++nfiles) > MAX_FILES) fatal(eOVF);
|
||||
(void)addFile(tkn_strt, nfiles);
|
||||
stringSP = tkn_strt;
|
||||
getToken();
|
||||
} /* end if */
|
||||
else if ((token == sFILE) && !(tknPtr->sParm.fileNumber))
|
||||
getToken();
|
||||
else
|
||||
error(eIDENT);
|
||||
}
|
||||
while (token == ',');
|
||||
if (token != ')') error(eRPAREN);
|
||||
else getToken();
|
||||
} /* End if */
|
||||
|
||||
/* Make sure that a semicolon follows the program-heading */
|
||||
|
||||
if (token != ';') error(eSEMICOLON);
|
||||
else getToken();
|
||||
|
||||
/* Set the POFF file header type */
|
||||
|
||||
poffSetFileType(poffHandle, FHT_PROGRAM, nfiles, pgmname);
|
||||
poffSetArchitecture(poffHandle, FHA_PCODE);
|
||||
|
||||
/* Discard the program name string */
|
||||
|
||||
stringSP = pgmname;
|
||||
|
||||
/* Process the optional 'uses-section'
|
||||
* FORM: uses-section = 'uses' [ uses-unit-list ] ';'
|
||||
*/
|
||||
|
||||
if (token == tUSES)
|
||||
{
|
||||
getToken();
|
||||
usesSection();
|
||||
}
|
||||
|
||||
/* Process the block */
|
||||
|
||||
block();
|
||||
if (token != '.') error(ePERIOD);
|
||||
pas_GenerateSimple(opEND);
|
||||
} /* end program */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void usesSection(void)
|
||||
{
|
||||
uint16_t saveToken;
|
||||
char defaultUnitFileName[FNAME_SIZE + 1];
|
||||
char *unitFileName = NULL;
|
||||
char *saveTknStrt;
|
||||
char *unitName;
|
||||
|
||||
TRACE(lstFile, "[usesSection]");
|
||||
|
||||
/* FORM: uses-section = 'uses' [ uses-unit-list ] ';'
|
||||
* FORM: uses-unit-list = unit-import {';' uses-unit-list }
|
||||
* FORM: unit-import = identifier ['in' non-empty-string ]
|
||||
*
|
||||
* On entry, token will point to the token just after
|
||||
* the 'uses' reservers word.
|
||||
*/
|
||||
|
||||
while (token == tIDENT)
|
||||
{
|
||||
/* Save the unit name identifier and skip over the identifier */
|
||||
|
||||
unitName = tkn_strt;
|
||||
getToken();
|
||||
|
||||
/* Check for the optional 'in' */
|
||||
|
||||
saveTknStrt = tkn_strt;
|
||||
if (token == tIN)
|
||||
{
|
||||
/* Skip over 'in' and verify that a string constant representing
|
||||
* the file name follows.
|
||||
*/
|
||||
|
||||
getToken();
|
||||
if (token != tSTRING_CONST) error(eSTRING);
|
||||
else
|
||||
{
|
||||
/* Save the unit file name and skip to the
|
||||
* next token.
|
||||
*/
|
||||
|
||||
unitFileName = tkn_strt;
|
||||
saveTknStrt = tkn_strt;
|
||||
getToken();
|
||||
}
|
||||
}
|
||||
|
||||
/* In any event, make sure that we have a non-NULL unit
|
||||
* file name.
|
||||
*/
|
||||
|
||||
if (!unitFileName)
|
||||
{
|
||||
/* Create a default filename */
|
||||
|
||||
(void)extension(unitName, ".pas", defaultUnitFileName, 1);
|
||||
unitFileName = defaultUnitFileName;
|
||||
}
|
||||
|
||||
/* Open the unit file */
|
||||
|
||||
saveToken = token;
|
||||
openNestedFile(unitFileName);
|
||||
FP->kind = eIsUnit;
|
||||
FP->section = eIsOtherSection;
|
||||
|
||||
/* Verify that this is a unit file */
|
||||
|
||||
if (token != tUNIT) error(eUNIT);
|
||||
else getToken();
|
||||
|
||||
/* Release the file name from the string stack */
|
||||
|
||||
stringSP = saveTknStrt;
|
||||
|
||||
/* Verify that the file provides the unit that we are looking
|
||||
* for (only one unit per file is supported)
|
||||
*/
|
||||
|
||||
if (token != tIDENT) error(eIDENT);
|
||||
else if (strcmp(unitName, tkn_strt) != 0) error(eUNITNAME);
|
||||
|
||||
/* Parse the interface from the unit file (token must refer
|
||||
* to the unit name on entry into unit().
|
||||
*/
|
||||
|
||||
unitInterface();
|
||||
closeNestedFile();
|
||||
|
||||
/* Verify the terminating semicolon */
|
||||
|
||||
token = saveToken;
|
||||
if (token != ';') error(eSEMICOLON);
|
||||
else getToken();
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
* pprgm.h
|
||||
* External Declarations associated with pprgm.c
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PPRGM_H
|
||||
#define __PPRGM_H
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void program(void);
|
||||
extern void usesSection(void);
|
||||
|
||||
#endif /* __PPRGM_H */
|
||||
@@ -0,0 +1,736 @@
|
||||
/****************************************************************************
|
||||
* pproc.c
|
||||
* Standard procedures (all called in pstm.c)
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "podefs.h"
|
||||
#include "pedefs.h"
|
||||
#include "pxdefs.h"
|
||||
|
||||
#include "pas.h"
|
||||
#include "pexpr.h"
|
||||
#include "pproc.h"
|
||||
#include "pgen.h" /* for pas_Generate*() */
|
||||
#include "ptkn.h"
|
||||
#include "ptbl.h" /* For parent symbol references */
|
||||
#include "perr.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Helpers for standard procedures */
|
||||
|
||||
static int16_t readProc (void); /* READ procedure */
|
||||
static void readText (uint16_t fileNumber); /* READ text file */
|
||||
static void readlnProc (void); /* READLN procedure */
|
||||
static void fileProc (uint16_t opcode); /* RESET/REWRITE/PAGE procedure */
|
||||
static int16_t writeProc (void); /* WRITE procedure */
|
||||
static void writeText (uint16_t fileNumber); /* WRITE text file */
|
||||
static void writelnProc (void); /* WRITELN procedure */
|
||||
|
||||
/* Helpers for less-than-standard procedures */
|
||||
|
||||
static void valProc (void); /* VAL procedure */
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* procedure val(const S : string; var V; var Code : word); */
|
||||
|
||||
static STYPE valSymbol[4];
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void primeBuiltInProcedures(void)
|
||||
{
|
||||
/* procedure val(const S : string; var V; var Code : word); */
|
||||
|
||||
valSymbol[0].sParm.p.nParms = 3;
|
||||
valSymbol[1].sKind = sSTRING;
|
||||
valSymbol[1].sParm.p.parent = parentString;
|
||||
valSymbol[2].sKind = sVAR_PARM;
|
||||
valSymbol[2].sParm.p.parent = parentInteger;
|
||||
valSymbol[3].sKind = sVAR_PARM;
|
||||
valSymbol[3].sParm.p.parent = parentInteger;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
void builtInProcedure(void)
|
||||
{
|
||||
TRACE(lstFile, "[builtInProcedure]");
|
||||
|
||||
/* Is the token a procedure? */
|
||||
|
||||
|
||||
if (token == tPROC)
|
||||
{
|
||||
/* Yes, process it procedure according to the extended token type */
|
||||
|
||||
switch (tknSubType)
|
||||
{
|
||||
/* Standard Procedures & Functions */
|
||||
|
||||
case txPAGE :
|
||||
fileProc(xWRITE_PAGE);
|
||||
break;
|
||||
|
||||
case txREAD :
|
||||
getToken();
|
||||
(void)readProc();
|
||||
break;
|
||||
|
||||
case txREADLN :
|
||||
readlnProc();
|
||||
break;
|
||||
|
||||
case txRESET :
|
||||
fileProc(xRESET);
|
||||
break;
|
||||
|
||||
case txREWRITE :
|
||||
fileProc(xREWRITE);
|
||||
break;
|
||||
|
||||
case txWRITE :
|
||||
getToken();
|
||||
(void)writeProc();
|
||||
break;
|
||||
|
||||
case txWRITELN :
|
||||
writelnProc();
|
||||
break;
|
||||
|
||||
case txGET :
|
||||
case txNEW :
|
||||
case txPACK :
|
||||
case txPUT :
|
||||
case txUNPACK :
|
||||
error(eNOTYET);
|
||||
getToken();
|
||||
break;
|
||||
|
||||
/* less-than-standard procedures */
|
||||
case txVAL :
|
||||
valProc();
|
||||
break;
|
||||
|
||||
/* Its not a recognized procedure */
|
||||
|
||||
default :
|
||||
error(eINVALIDPROC);
|
||||
break;
|
||||
|
||||
} /* end switch */
|
||||
} /* end if */
|
||||
} /* end builtInProcedure */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
int actualParameterSize(STYPE *procPtr, int parmNo)
|
||||
{
|
||||
/* These sizes must agree with the sizes used in actualParameterListg()
|
||||
* below.
|
||||
*/
|
||||
|
||||
STYPE *typePtr = procPtr[parmNo].sParm.v.parent;
|
||||
switch (typePtr->sKind)
|
||||
{
|
||||
case sINT :
|
||||
case sSUBRANGE :
|
||||
case sSCALAR :
|
||||
case sSET_OF :
|
||||
default:
|
||||
return sINT_SIZE;
|
||||
break;
|
||||
case sCHAR :
|
||||
return sCHAR_SIZE;
|
||||
break;
|
||||
case sREAL :
|
||||
return sREAL_SIZE;
|
||||
break;
|
||||
case sSTRING :
|
||||
case sRSTRING :
|
||||
return sRSTRING_SIZE;
|
||||
break;
|
||||
case sARRAY :
|
||||
case sRECORD :
|
||||
return typePtr->sParm.t.asize;
|
||||
break;
|
||||
case sVAR_PARM :
|
||||
return sPTR_SIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
int actualParameterList(STYPE *procPtr)
|
||||
{
|
||||
STYPE *typePtr;
|
||||
register int nParms = 0;
|
||||
int size = 0;
|
||||
|
||||
TRACE(lstFile,"[actualParameterList]");
|
||||
|
||||
/* Processes the (optional) actual-parameter-list associated with
|
||||
* a function or procedure call:
|
||||
*
|
||||
* FORM: procedure-method-statement =
|
||||
* procedure-method-specifier [ actual-parameter-list ]
|
||||
* FORM: function-designator = function-identifier [ actual-parameter-list ]
|
||||
*
|
||||
*
|
||||
* On entry, 'token' refers to the token just AFTER the procedure
|
||||
* function identifier.
|
||||
*
|
||||
* FORM: actual-parameter-list =
|
||||
* '(' actual-parameter { ',' actual-parameter } ')'
|
||||
* FORM: actual-parameter =
|
||||
* expression | variable-access |
|
||||
* procedure-identifier | function-identifier
|
||||
*/
|
||||
|
||||
/* If this procedure requires parameters, get them and make sure that
|
||||
* they match in type and number
|
||||
*/
|
||||
|
||||
if (procPtr->sParm.p.nParms)
|
||||
{
|
||||
/* If it requires parameters, then the actual-parameter-list must
|
||||
* be present and must begin with '('
|
||||
*/
|
||||
|
||||
if (token != '(') error (eLPAREN);
|
||||
else getToken();
|
||||
|
||||
/* Loop to process the expected number of parameters. The formal
|
||||
* argument descriptions follow the procedure/function description
|
||||
* as an array of variable declarations. (These sizes below must
|
||||
* agree with actualParameterSize() above);
|
||||
*/
|
||||
|
||||
for (nParms = 1; nParms <= procPtr->sParm.p.nParms; nParms++)
|
||||
{
|
||||
typePtr = procPtr[nParms].sParm.v.parent;
|
||||
switch (procPtr[nParms].sKind)
|
||||
{
|
||||
case sINT :
|
||||
expression(exprInteger, typePtr);
|
||||
size += sINT_SIZE;
|
||||
break;
|
||||
case sCHAR :
|
||||
expression(exprChar, typePtr);
|
||||
size += sCHAR_SIZE;
|
||||
break;
|
||||
case sREAL :
|
||||
expression(exprReal, typePtr);
|
||||
size += sREAL_SIZE;
|
||||
break;
|
||||
case sSTRING :
|
||||
case sRSTRING :
|
||||
expression(exprString, typePtr);
|
||||
size += sRSTRING_SIZE;
|
||||
break;
|
||||
case sSUBRANGE :
|
||||
expression(exprInteger, typePtr);
|
||||
size += sINT_SIZE;
|
||||
break;
|
||||
case sSCALAR :
|
||||
expression(exprScalar, typePtr);
|
||||
size += sINT_SIZE;
|
||||
break;
|
||||
case sSET_OF :
|
||||
expression(exprSet, typePtr);
|
||||
size += sINT_SIZE;
|
||||
break;
|
||||
case sARRAY :
|
||||
expression(exprArray, typePtr);
|
||||
size += typePtr->sParm.t.asize;
|
||||
break;
|
||||
case sRECORD :
|
||||
expression(exprRecord, typePtr);
|
||||
size += typePtr->sParm.t.asize;
|
||||
break;
|
||||
case sVAR_PARM :
|
||||
if (typePtr)
|
||||
{
|
||||
switch (typePtr->sParm.t.type)
|
||||
{
|
||||
case sINT :
|
||||
varParm(exprIntegerPtr, typePtr);
|
||||
size += sPTR_SIZE;
|
||||
break;
|
||||
case sBOOLEAN :
|
||||
varParm(exprBooleanPtr, typePtr);
|
||||
size += sPTR_SIZE;
|
||||
break;
|
||||
case sCHAR :
|
||||
varParm(exprCharPtr, typePtr);
|
||||
size += sPTR_SIZE;
|
||||
break;
|
||||
case sREAL :
|
||||
varParm(exprRealPtr, typePtr);
|
||||
size += sPTR_SIZE;
|
||||
break;
|
||||
case sARRAY :
|
||||
varParm(exprArrayPtr, typePtr);
|
||||
size += sPTR_SIZE;
|
||||
break;
|
||||
case sRECORD :
|
||||
varParm(exprRecordPtr, typePtr);
|
||||
size += sPTR_SIZE;
|
||||
break;
|
||||
default :
|
||||
error(eVARPARMTYPE);
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end if */
|
||||
else
|
||||
error(eVARPARMTYPE);
|
||||
break;
|
||||
default :
|
||||
error (eNPARMS);
|
||||
} /* end switch */
|
||||
|
||||
if (nParms < procPtr->sParm.p.nParms)
|
||||
{
|
||||
if (token != ',') error (eCOMMA);
|
||||
else getToken();
|
||||
} /* end if */
|
||||
} /* end for */
|
||||
|
||||
if (token != ')') error (eRPAREN);
|
||||
else getToken();
|
||||
|
||||
} /* end if */
|
||||
|
||||
return size;
|
||||
|
||||
} /* end actualParameterList */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static int16_t readProc(void)
|
||||
{
|
||||
uint16_t fileNumber = 0;
|
||||
|
||||
TRACE(lstFile, "[readProc]");
|
||||
|
||||
/* FORM:
|
||||
* (1) Binary READ: read '(' file-variable ')'
|
||||
* (2) Test READ: read read-parameter-list
|
||||
* FORM: read-parameter-list =
|
||||
* '(' [ file-variable ',' ] variable-access { ',' variable-access } ')'
|
||||
*/
|
||||
|
||||
if (token != '(') error (eLPAREN); /* Skip over '(' */
|
||||
else getToken();
|
||||
|
||||
/* Get file number */
|
||||
|
||||
if (token == sFILE)
|
||||
{
|
||||
fileNumber = tknPtr->sParm.fileNumber;
|
||||
getToken();
|
||||
} /* end if */
|
||||
if (token == ',') getToken();
|
||||
|
||||
/* Determine if this is a text or binary file */
|
||||
|
||||
if (!(files [fileNumber].defined)) error (eUNDEFILE);
|
||||
else if (files [fileNumber].ftype == sCHAR)
|
||||
{
|
||||
readText (fileNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
pas_GenerateLevelReference(opLAS, files[fileNumber].flevel, files [fileNumber].faddr);
|
||||
pas_GenerateDataOperation(opPUSH, files[fileNumber].fsize);
|
||||
pas_GenerateIoOperation(xREAD_BINARY, fileNumber);
|
||||
} /* end else */
|
||||
|
||||
if (token != ')') error (eRPAREN);
|
||||
else getToken();
|
||||
|
||||
return (fileNumber);
|
||||
} /* end readProc */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void readText (uint16_t fileNumber)
|
||||
{
|
||||
STYPE *rPtr;
|
||||
|
||||
TRACE(lstFile, "[readText]");
|
||||
|
||||
/* The general form is <VAR parm>, <VAR parm>,... */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
/* SPECIAL CASE: Array of type CHAR without indexing */
|
||||
|
||||
case sARRAY :
|
||||
rPtr = tknPtr->sParm.v.parent;
|
||||
if (((rPtr) && (rPtr->sKind == sTYPE)) &&
|
||||
(rPtr->sParm.t.type == sCHAR) &&
|
||||
(getNextCharacter(true) != '['))
|
||||
{
|
||||
pas_GenerateStackReference(opLAS, rPtr);
|
||||
pas_GenerateDataOperation(opPUSH, rPtr->sParm.v.size);
|
||||
pas_GenerateIoOperation(xREAD_STRING, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -(sPTR_SIZE+sINT_SIZE));
|
||||
} /* end if */
|
||||
|
||||
/* Otherwise, we fall through to process the ARRAY like any */
|
||||
/* expression */
|
||||
|
||||
default :
|
||||
|
||||
switch (varParm(exprUnknown, NULL))
|
||||
{
|
||||
case exprIntegerPtr :
|
||||
pas_GenerateIoOperation(xREAD_INT, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -sPTR_SIZE);
|
||||
break;
|
||||
|
||||
case exprCharPtr :
|
||||
pas_GenerateIoOperation(xREAD_CHAR, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -sPTR_SIZE);
|
||||
break;
|
||||
|
||||
case exprRealPtr :
|
||||
pas_GenerateIoOperation(xREAD_REAL, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -sPTR_SIZE);
|
||||
break;
|
||||
|
||||
default :
|
||||
error(eINVARG);
|
||||
break;
|
||||
} /* end switch */
|
||||
break;
|
||||
|
||||
} /* end switch */
|
||||
|
||||
if (token == ',') getToken();
|
||||
else return;
|
||||
|
||||
} /* end for */
|
||||
|
||||
} /* end readText */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void readlnProc(void) /* READLN procedure */
|
||||
{
|
||||
int32_t fileNumber;
|
||||
|
||||
TRACE(lstFile, "[readlnProc]");
|
||||
|
||||
/* FORM: Just like READ */
|
||||
|
||||
getToken();
|
||||
if (token == '(')
|
||||
fileNumber = readProc();
|
||||
|
||||
/* skip to end-of-line mark in the file (NOTE: No check is made,
|
||||
* but this is meaningful only for a test file).
|
||||
*/
|
||||
|
||||
pas_GenerateIoOperation(xREADLN, fileNumber);
|
||||
|
||||
} /* end readlnProc */
|
||||
|
||||
/****************************************************************************/
|
||||
/* REWRITE/RESET/PAGE procedure call -- REWRITE sets the file pointer to the
|
||||
* beginning of the file and prepares the file for write access; RESET is
|
||||
* similar except that it prepares the file for read access; PAGE simply
|
||||
* writes a form-feed to the file (no check is made, but is meaningful only
|
||||
* for a text file). */
|
||||
|
||||
static void fileProc (uint16_t opcode)
|
||||
{
|
||||
TRACE(lstFile, "[fileProc]");
|
||||
|
||||
/* FORM: RESET|REWRITE(<file number>) */
|
||||
|
||||
getToken();
|
||||
if (token != '(') error(eLPAREN);
|
||||
else getToken();
|
||||
if (token != sFILE) error(eFILE);
|
||||
else {
|
||||
pas_GenerateIoOperation(opcode, tknPtr->sParm.fileNumber);
|
||||
getToken();
|
||||
if (token != ')') error(eRPAREN);
|
||||
else getToken();
|
||||
} /* end else */
|
||||
|
||||
} /* End fileProc */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static int16_t writeProc(void)
|
||||
{
|
||||
uint16_t fileNumber = 0;
|
||||
|
||||
TRACE(lstFile, "[writeProc]");
|
||||
|
||||
/* FORM: (1) Binary WRITE: WRITE(<fileNumber>);
|
||||
* (2) Test WRITE: WRITE([<fileNumber>], arg1 [,arg2 [...]]) */
|
||||
|
||||
if (token != '(') error(eLPAREN); /* Skip over '(' */
|
||||
else getToken();
|
||||
|
||||
/* Get file number */
|
||||
|
||||
if (token == sFILE) {
|
||||
fileNumber = tknPtr->sParm.fileNumber;
|
||||
getToken();
|
||||
} /* end if */
|
||||
if (token == ',') getToken();
|
||||
|
||||
/* Determine if this is a text or binary file */
|
||||
|
||||
if (!(files [fileNumber].defined)) error(eUNDEFILE);
|
||||
else if (files [fileNumber].ftype == sCHAR)
|
||||
writeText(fileNumber);
|
||||
else {
|
||||
pas_GenerateLevelReference(opLAS, files[fileNumber].flevel, files [fileNumber].faddr);
|
||||
pas_GenerateDataOperation(opPUSH, files[fileNumber].fsize);
|
||||
pas_GenerateIoOperation(xWRITE_BINARY, fileNumber);
|
||||
} /* end else */
|
||||
|
||||
if (token != ')') error(eRPAREN);
|
||||
else getToken();
|
||||
return(fileNumber);
|
||||
} /* end writeProc */
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
static void writeText (uint16_t fileNumber)
|
||||
{
|
||||
exprType writeType;
|
||||
STYPE *wPtr;
|
||||
|
||||
TRACE(lstFile, "[writeText]");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* The general form is <expression>, <expression>, ... However,
|
||||
* there are a few unique things that must be handled as special
|
||||
* cases
|
||||
*/
|
||||
|
||||
switch (token)
|
||||
{
|
||||
/* const strings -- either literal constants (tSTRING_CONST)
|
||||
* or defined string constant symbols (sSTRING_CONST)
|
||||
*/
|
||||
|
||||
case tSTRING_CONST :
|
||||
{
|
||||
/* Add the literal string constant to the RO data section
|
||||
* and receive the offset to the data.
|
||||
*/
|
||||
|
||||
uint32_t offset = poffAddRoDataString(poffHandle, tkn_strt);
|
||||
|
||||
/* Set the offset and size on the stack (order is important) */
|
||||
|
||||
pas_GenerateDataOperation(opLAC, (uint16_t)offset);
|
||||
pas_GenerateDataOperation(opPUSH, strlen(tkn_strt));
|
||||
|
||||
pas_GenerateIoOperation(xWRITE_STRING, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -(sPTR_SIZE + sINT_SIZE));
|
||||
stringSP = tkn_strt;
|
||||
getToken();
|
||||
}
|
||||
break;
|
||||
|
||||
case sSTRING_CONST :
|
||||
pas_GenerateDataOperation(opLAC, (uint16_t)tknPtr->sParm.s.offset);
|
||||
pas_GenerateDataOperation(opPUSH, (uint16_t)tknPtr->sParm.s.size);
|
||||
pas_GenerateIoOperation(xWRITE_STRING, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -(sPTR_SIZE + sINT_SIZE));
|
||||
getToken();
|
||||
break;
|
||||
|
||||
/* Array of type CHAR without indexing */
|
||||
|
||||
case sARRAY :
|
||||
wPtr = tknPtr->sParm.v.parent;
|
||||
if (((wPtr) && (wPtr->sKind == sTYPE)) &&
|
||||
(wPtr->sParm.t.type == sCHAR) &&
|
||||
(getNextCharacter(true) != '['))
|
||||
{
|
||||
pas_GenerateStackReference(opLAS, wPtr);
|
||||
pas_GenerateDataOperation(opPUSH, wPtr->sParm.v.size);
|
||||
pas_GenerateIoOperation(xWRITE_STRING, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -(sPTR_SIZE + sINT_SIZE));
|
||||
break;
|
||||
} /* end if */
|
||||
|
||||
/* Otherwise, we fall through to process the ARRAY like any */
|
||||
/* expression */
|
||||
|
||||
default :
|
||||
writeType = expression(exprUnknown, NULL);
|
||||
switch (writeType)
|
||||
{
|
||||
case exprInteger :
|
||||
pas_GenerateIoOperation(xWRITE_INT, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -sINT_SIZE);
|
||||
break;
|
||||
|
||||
case exprBoolean :
|
||||
error(eNOTYET);
|
||||
break;
|
||||
|
||||
case exprChar :
|
||||
pas_GenerateIoOperation(xWRITE_CHAR, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -sINT_SIZE);
|
||||
break;
|
||||
|
||||
case exprReal :
|
||||
pas_GenerateIoOperation(xWRITE_REAL, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -sREAL_SIZE);
|
||||
break;
|
||||
|
||||
case exprString :
|
||||
case exprStkString :
|
||||
pas_GenerateIoOperation(xWRITE_STRING, fileNumber);
|
||||
pas_GenerateDataOperation(opINDS, -sRSTRING_SIZE);
|
||||
break;
|
||||
|
||||
default :
|
||||
error(eWRITEPARM);
|
||||
break;
|
||||
|
||||
} /* end switch */
|
||||
break;
|
||||
|
||||
} /* end switch */
|
||||
|
||||
if (token == ',') getToken();
|
||||
else return;
|
||||
|
||||
} /* end for */
|
||||
|
||||
} /* end writeText */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void writelnProc(void) /* WRITELN procedure */
|
||||
{
|
||||
int32_t fileNumber = 0;
|
||||
|
||||
TRACE(lstFile, "[writelnProc]");
|
||||
|
||||
/* FORM: Just like WRITE */
|
||||
|
||||
getToken();
|
||||
if (token == '(')
|
||||
{
|
||||
fileNumber = writeProc();
|
||||
}
|
||||
|
||||
/* Skip to past end-of-line mark in the file (NOTE: No check is made, but
|
||||
* this is meaningful only for a test file).
|
||||
*/
|
||||
|
||||
pas_GenerateIoOperation(xWRITELN, fileNumber);
|
||||
|
||||
} /* end writelnProc */
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void valProc(void) /* VAL procedure */
|
||||
{
|
||||
int size;
|
||||
|
||||
TRACE(lstFile, "[valProc]");
|
||||
|
||||
/* Declaration:
|
||||
* procedure val(const S : string; var V; var Code : word);
|
||||
*
|
||||
* Description:
|
||||
* val() converts the value represented in the string S to a numerical
|
||||
* value, and stores this value in the variable V, which can be of type
|
||||
* Longint, Real and Byte. If the conversion isn��t succesfull, then the
|
||||
* parameter Code contains the index of the character in S which
|
||||
* prevented the conversion. The string S is allowed to contain spaces
|
||||
* in the beginning.
|
||||
*
|
||||
* The string S can contain a number in decimal, hexadecimal, binary or
|
||||
* octal format, as described in the language reference.
|
||||
*
|
||||
* Errors:
|
||||
* If the conversion doesn��t succeed, the value of Code indicates the
|
||||
* position where the conversion went wrong.
|
||||
*/
|
||||
|
||||
/* Skip over the 'val' identifer */
|
||||
|
||||
getToken();
|
||||
|
||||
/* Setup the actual-parameter-list */
|
||||
|
||||
size = actualParameterList(valSymbol);
|
||||
|
||||
/* Generate the built-in procedure call. NOTE the procedure call
|
||||
* logic will release the parameters from the stack saving us from
|
||||
* having to generate the INDS here.
|
||||
*/
|
||||
|
||||
pas_BuiltInFunctionCall(lbVAL);
|
||||
|
||||
} /* end writelnProc */
|
||||
|
||||
/***********************************************************************/
|
||||
@@ -0,0 +1,49 @@
|
||||
/***************************************************************************
|
||||
* pproc.h
|
||||
* External Declarations associated with PPROC.C
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PPROC_H
|
||||
#define __PPROC_H
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void primeBuiltInProcedures(void);
|
||||
extern void builtInProcedure(void);
|
||||
extern int actualParameterSize(STYPE *procPtr, int parmNo);
|
||||
extern int actualParameterList(STYPE *procPtr);
|
||||
|
||||
#endif /* __PPROC_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
* pstm.h
|
||||
* External Declarations associated with pstm.c
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PSTM_H
|
||||
#define __PSTM_H
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void statement (void); /* Process Statement */
|
||||
extern void compoundStatement (void); /* Compound statement */
|
||||
|
||||
#endif /* __PSTM_H */
|
||||
@@ -0,0 +1,692 @@
|
||||
/***************************************************************
|
||||
* ptbl.c
|
||||
* Table Management Package
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* Included Files
|
||||
***************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "pedefs.h"
|
||||
|
||||
#include "pas.h"
|
||||
#include "ptbl.h"
|
||||
#include "perr.h"
|
||||
|
||||
/***************************************************************
|
||||
* Private Function Prototypes
|
||||
***************************************************************/
|
||||
|
||||
static STYPE *addSymbol(char *name, int16_t type);
|
||||
|
||||
/***************************************************************
|
||||
* Public Variables
|
||||
***************************************************************/
|
||||
|
||||
STYPE *parentInteger = NULL;
|
||||
STYPE *parentString = NULL;
|
||||
|
||||
/***************************************************************
|
||||
* Private Variables
|
||||
***************************************************************/
|
||||
/* NOTES in the following:
|
||||
* (1) Standard Pascal reserved word
|
||||
* (2) Standard Pascal Function
|
||||
* (3) Standard Pascal Procedure
|
||||
* (4) Extended (or non-standard) Pascal reserved word
|
||||
* (5) Extended (or non-standard) Pascal function
|
||||
* (6) Extended (or non-standard) Pascal procedure
|
||||
*/
|
||||
|
||||
static const RTYPE rsw[] = /* Reserved word list */
|
||||
{
|
||||
{"ABS", tFUNC, txABS}, /* (2) */
|
||||
{"AND", tAND, txNONE}, /* (1) */
|
||||
{"ARCTAN", tFUNC, txARCTAN}, /* (2) */
|
||||
{"ARRAY", tARRAY, txNONE}, /* (1) */
|
||||
{"BEGIN", tBEGIN, txNONE}, /* (1) */
|
||||
{"CASE", tCASE, txNONE}, /* (1) */
|
||||
{"CHR", tFUNC, txCHR}, /* (2) */
|
||||
{"CONST", tCONST, txNONE}, /* (1) */
|
||||
{"COS", tFUNC, txCOS}, /* (2) */
|
||||
{"DIV", tDIV, txNONE}, /* (1) */
|
||||
{"DO", tDO, txNONE}, /* (1) */
|
||||
{"DOWNTO", tDOWNTO, txNONE}, /* (1) */
|
||||
{"ELSE", tELSE, txNONE}, /* (1) */
|
||||
{"END", tEND, txNONE}, /* (1) */
|
||||
{"EOF", tFUNC, txEOF}, /* (2) */
|
||||
{"EOLN", tFUNC, txEOLN}, /* (2) */
|
||||
{"EXP", tFUNC, txEXP}, /* (2) */
|
||||
{"FILE", tFILE, txNONE}, /* (1) */
|
||||
{"FOR", tFOR, txNONE}, /* (1) */
|
||||
{"FUNCTION", tFUNCTION, txNONE}, /* (1) */
|
||||
{"GET", tPROC, txGET}, /* (3) */
|
||||
{"GETENV", tFUNC, txGETENV}, /* (5) */
|
||||
{"GOTO", tGOTO, txNONE}, /* (1) */
|
||||
{"IF", tIF, txNONE}, /* (1) */
|
||||
{"IMPLEMENTATION", tIMPLEMENTATION, txNONE}, /* (4) */
|
||||
{"IN", tIN, txNONE}, /* (1) */
|
||||
{"INTERFACE", tINTERFACE, txNONE}, /* (4) */
|
||||
{"LABEL", tLABEL, txNONE}, /* (1) */
|
||||
{"LN", tFUNC, txLN}, /* (2) */
|
||||
{"MOD", tMOD, txNONE}, /* (1) */
|
||||
{"NEW", tPROC, txNEW}, /* (3) */
|
||||
{"NOT", tNOT, txNONE}, /* (1) */
|
||||
{"ODD", tFUNC, txODD}, /* (2) */
|
||||
{"OF", tOF, txNONE}, /* (1) */
|
||||
{"OR", tOR, txNONE}, /* (1) */
|
||||
{"ORD", tFUNC, txORD}, /* (2) */
|
||||
{"PACK", tPROC, txPACK}, /* (3) */
|
||||
{"PACKED", tPACKED, txNONE}, /* (1) */
|
||||
{"PAGE", tPROC, txPAGE}, /* (3) */
|
||||
{"PRED", tFUNC, txPRED}, /* (2) */
|
||||
{"PROCEDURE", tPROCEDURE, txNONE}, /* (1) */
|
||||
{"PROGRAM", tPROGRAM, txNONE}, /* (1) */
|
||||
{"PUT", tPROC, txPUT}, /* (3) */
|
||||
{"READ", tPROC, txREAD}, /* (3) */
|
||||
{"READLN", tPROC, txREADLN}, /* (3) */
|
||||
{"RECORD", tRECORD, txNONE}, /* (1) */
|
||||
{"REPEAT", tREPEAT, txNONE}, /* (1) */
|
||||
{"RESET", tPROC, txRESET}, /* (3) */
|
||||
{"REWRITE", tPROC, txREWRITE}, /* (3) */
|
||||
{"ROUND", tFUNC, txROUND}, /* (2) */
|
||||
{"SET", tSET, txNONE}, /* (1) */
|
||||
{"SHL", tSHL, txNONE}, /* (4) */
|
||||
{"SHR", tSHR, txNONE}, /* (4) */
|
||||
{"SIN", tFUNC, txSIN}, /* (2) */
|
||||
{"SQR", tFUNC, txSQR}, /* (2) */
|
||||
{"SQRT", tFUNC, txSQRT}, /* (2) */
|
||||
{"SUCC", tFUNC, txSUCC}, /* (2) */
|
||||
{"THEN", tTHEN, txNONE}, /* (1) */
|
||||
{"TO", tTO, txNONE}, /* (1) */
|
||||
{"TRUNC", tFUNC, txTRUNC}, /* (2) */
|
||||
{"TYPE", tTYPE, txNONE}, /* (1) */
|
||||
{"UNIT", tUNIT, txNONE}, /* (4) */
|
||||
{"UNPACK", tPROC, txUNPACK}, /* (3) */
|
||||
{"UNTIL", tUNTIL, txNONE}, /* (1) */
|
||||
{"USES", tUSES, txNONE}, /* (4) */
|
||||
{"VAL", tPROC, txVAL}, /* (6) */
|
||||
{"VAR", tVAR, txNONE}, /* (1) */
|
||||
{"WHILE", tWHILE, txNONE}, /* (1) */
|
||||
{"WITH", tWITH, txNONE}, /* (1) */
|
||||
{"WRITE", tPROC, txWRITE}, /* (3) */
|
||||
{"WRITELN", tPROC, txWRITELN}, /* (3) */
|
||||
{NULL, 0, txNONE} /* List terminator */
|
||||
};
|
||||
|
||||
static STYPE *symbolTable; /* Symbol Table */
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
const RTYPE *findReservedWord (char *name)
|
||||
{
|
||||
register const RTYPE *ptr; /* Point into reserved word list */
|
||||
register int16_t cmp; /* 0=equal; >0=past it */
|
||||
|
||||
for (ptr = rsw; (ptr->rname); ptr++) /* Try each each reserved word */
|
||||
{
|
||||
cmp = strcmp(ptr->rname, name); /* Check if names match */
|
||||
if (!cmp) /* Check if names match */
|
||||
return ptr; /* Return pointer to entry if match */
|
||||
else if (cmp > 0) /* Exit early if we are past it */
|
||||
break;
|
||||
} /* end for */
|
||||
|
||||
return (RTYPE*)NULL; /* return NULL pointer if no match */
|
||||
|
||||
} /* fnd findReservedWord */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *findSymbol (char *inName)
|
||||
{
|
||||
register int16_t i; /* loop index */
|
||||
|
||||
for (i=nsym-1; i>=sym_strt; i--)
|
||||
if (symbolTable[i].sName)
|
||||
if (!strcmp(symbolTable[i].sName, inName))
|
||||
return &symbolTable[i];
|
||||
return (STYPE*)NULL;
|
||||
|
||||
} /* end findSymbol */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static STYPE *addSymbol(char *name, int16_t type)
|
||||
{
|
||||
TRACE(lstFile,"[addSymbol]");
|
||||
|
||||
/* Check for Symbol Table overflow */
|
||||
if (nsym >= MAX_SYM) {
|
||||
|
||||
fatal(eOVF);
|
||||
return (STYPE *)NULL;
|
||||
|
||||
} /* end if */
|
||||
else {
|
||||
|
||||
/* Clear all elements of the symbol table entry */
|
||||
memset(&symbolTable[nsym], 0, sizeof(STYPE));
|
||||
|
||||
/* Set the elements which are independent of sKind */
|
||||
symbolTable[nsym].sName = name;
|
||||
symbolTable[nsym].sKind = type;
|
||||
symbolTable[nsym].sLevel = level;
|
||||
|
||||
return &symbolTable[nsym++];
|
||||
|
||||
} /* end else */
|
||||
|
||||
} /* end addSymbol */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addTypeDefine(char *name, uint8_t type, uint16_t size, STYPE *parent)
|
||||
{
|
||||
STYPE *typePtr;
|
||||
|
||||
TRACE(lstFile,"[addTypeDefine]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
|
||||
typePtr = addSymbol(name, sTYPE);
|
||||
if (typePtr)
|
||||
{
|
||||
/* Add the type definition to the symbol table
|
||||
* NOTES:
|
||||
* 1. The minValue and maxValue fields (for scalar and subrange)
|
||||
* types must be set external to this function
|
||||
* 2. For most variables, allocated size/type (rsize/rtype) and
|
||||
* the clone size/type are the same. If this is not the case,
|
||||
* external logic will need to clarify this as well.
|
||||
* 3. We assume that there are no special flags associated with
|
||||
* the type.
|
||||
*/
|
||||
|
||||
typePtr->sParm.t.type = type;
|
||||
typePtr->sParm.t.rtype = type;
|
||||
typePtr->sParm.t.flags = 0;
|
||||
typePtr->sParm.t.asize = size;
|
||||
typePtr->sParm.t.rsize = size;
|
||||
typePtr->sParm.t.parent = parent;
|
||||
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new constant symbol */
|
||||
|
||||
return typePtr;
|
||||
|
||||
} /* end addTypeDefine */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addConstant(char *name, uint8_t type, int32_t *value, STYPE *parent)
|
||||
{
|
||||
STYPE *constPtr;
|
||||
|
||||
TRACE(lstFile,"[addConstant]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
constPtr = addSymbol(name, type);
|
||||
if (constPtr) {
|
||||
|
||||
/* Add the value of the constant to the symbol table */
|
||||
if (type == tREAL_CONST)
|
||||
constPtr->sParm.c.val.f = *((double*) value);
|
||||
else
|
||||
constPtr->sParm.c.val.i = *value;
|
||||
constPtr->sParm.c.parent = parent;
|
||||
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new constant symbol */
|
||||
|
||||
return constPtr;
|
||||
|
||||
} /* end addConstant */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addStringConst(char *name, uint32_t offset, uint32_t size)
|
||||
{
|
||||
STYPE *stringPtr;
|
||||
|
||||
TRACE(lstFile,"[addStringConst]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
|
||||
stringPtr = addSymbol(name, sSTRING_CONST);
|
||||
if (stringPtr)
|
||||
{
|
||||
/* Add the value of the constant to the symbol table */
|
||||
|
||||
stringPtr->sParm.s.offset = offset;
|
||||
stringPtr->sParm.s.size = size;
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new string symbol */
|
||||
|
||||
return stringPtr;
|
||||
|
||||
} /* end addString */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addFile(char *name, uint16_t fileNumber)
|
||||
{
|
||||
STYPE *filePtr;
|
||||
|
||||
TRACE(lstFile,"[addFile]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
filePtr = addSymbol(name, sFILE);
|
||||
if (filePtr) {
|
||||
|
||||
/* Add the fileNumber to the symbol table */
|
||||
filePtr->sParm.fileNumber = fileNumber;
|
||||
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new file symbol */
|
||||
|
||||
return filePtr;
|
||||
|
||||
} /* end addFile */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addProcedure(char *name, uint8_t type, uint16_t label,
|
||||
uint16_t nParms, STYPE *parent)
|
||||
{
|
||||
STYPE *procPtr;
|
||||
|
||||
TRACE(lstFile,"[addProcedure]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
procPtr = addSymbol(name, type);
|
||||
if (procPtr)
|
||||
{
|
||||
/* Add the procedure/function definition to the symbol table */
|
||||
|
||||
procPtr->sParm.p.label = label;
|
||||
procPtr->sParm.p.nParms = nParms;
|
||||
procPtr->sParm.p.flags = 0;
|
||||
procPtr->sParm.p.symIndex = 0;
|
||||
procPtr->sParm.p.parent = parent;
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new procedure/function symbol */
|
||||
|
||||
return procPtr;
|
||||
|
||||
} /* end addProcedure */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addVariable(char *name, uint8_t type, uint16_t offset,
|
||||
uint16_t size, STYPE *parent)
|
||||
{
|
||||
STYPE *varPtr;
|
||||
|
||||
TRACE(lstFile,"[addVariable]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
|
||||
varPtr = addSymbol(name, type);
|
||||
if (varPtr)
|
||||
{
|
||||
/* Add the variable to the symbol table */
|
||||
|
||||
varPtr->sParm.v.offset = offset;
|
||||
varPtr->sParm.v.size = size;
|
||||
varPtr->sParm.v.flags = 0;
|
||||
varPtr->sParm.v.symIndex = 0;
|
||||
varPtr->sParm.v.parent = parent;
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new variable symbol */
|
||||
|
||||
return varPtr;
|
||||
|
||||
} /* end addFile */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addLabel(char *name, uint16_t label)
|
||||
{
|
||||
STYPE *labelPtr;
|
||||
|
||||
TRACE(lstFile,"[addLabel]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
|
||||
labelPtr = addSymbol(name, sLABEL);
|
||||
if (labelPtr)
|
||||
{
|
||||
/* Add the label to the symbol table */
|
||||
|
||||
labelPtr->sParm.l.label = label;
|
||||
labelPtr->sParm.l.unDefined = true;
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new label symbol */
|
||||
|
||||
return labelPtr;
|
||||
|
||||
} /* end addFile */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
STYPE *addField(char *name, STYPE *record)
|
||||
{
|
||||
STYPE *fieldPtr;
|
||||
|
||||
TRACE(lstFile,"[addField]");
|
||||
|
||||
/* Get a slot in the symbol table */
|
||||
fieldPtr = addSymbol(name, sRECORD_OBJECT);
|
||||
if (fieldPtr) {
|
||||
|
||||
/* Add the field to the symbol table */
|
||||
fieldPtr->sParm.r.record = record;
|
||||
|
||||
} /* end if */
|
||||
|
||||
/* Return a pointer to the new variable symbol */
|
||||
|
||||
return fieldPtr;
|
||||
|
||||
} /* end addField */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
void primeSymbolTable(unsigned long symbolTableSize)
|
||||
{
|
||||
int32_t trueValue = -1;
|
||||
int32_t falseValue = 0;
|
||||
int32_t maxintValue = MAXINT;
|
||||
STYPE *typePtr;
|
||||
register int16_t i;
|
||||
|
||||
TRACE(lstFile,"[primeSymbolTable]");
|
||||
|
||||
/* Allocate and initialize symbol table */
|
||||
|
||||
symbolTable = malloc(symbolTableSize * sizeof(STYPE));
|
||||
if (!symbolTable)
|
||||
{
|
||||
fatal(eNOMEMORY);
|
||||
}
|
||||
|
||||
nsym = 0;
|
||||
|
||||
/* Add the standard constants to the symbol table */
|
||||
|
||||
(void)addConstant("TRUE", tBOOLEAN_CONST, &trueValue, NULL);
|
||||
(void)addConstant("FALSE", tBOOLEAN_CONST, &falseValue, NULL);
|
||||
(void)addConstant("MAXINT", tINT_CONST, &maxintValue, NULL);
|
||||
(void)addConstant("NIL", tNIL, &falseValue, NULL);
|
||||
|
||||
/* Add the standard types to the symbol table */
|
||||
|
||||
typePtr = addTypeDefine("INTEGER", sINT, sINT_SIZE, NULL);
|
||||
if (typePtr)
|
||||
{
|
||||
parentInteger = typePtr;
|
||||
typePtr->sParm.t.minValue = MININT;
|
||||
typePtr->sParm.t.maxValue = MAXINT;
|
||||
} /* end if */
|
||||
|
||||
typePtr = addTypeDefine("BOOLEAN", sBOOLEAN, sBOOLEAN_SIZE, NULL);
|
||||
if (typePtr)
|
||||
{
|
||||
typePtr->sParm.t.minValue = falseValue;
|
||||
typePtr->sParm.t.maxValue = trueValue;
|
||||
} /* end if */
|
||||
|
||||
typePtr = addTypeDefine("REAL", sREAL, sREAL_SIZE, NULL);
|
||||
|
||||
typePtr = addTypeDefine("CHAR", sCHAR, sCHAR_SIZE, NULL);
|
||||
if (typePtr)
|
||||
{
|
||||
typePtr->sParm.t.minValue = MINCHAR;
|
||||
typePtr->sParm.t.maxValue = MAXCHAR;
|
||||
} /* end if */
|
||||
|
||||
typePtr = addTypeDefine("TEXT", sFILE_OF, sCHAR_SIZE, NULL);
|
||||
if (typePtr)
|
||||
{
|
||||
typePtr->sParm.t.subType = sCHAR;
|
||||
typePtr->sParm.t.minValue = MINCHAR;
|
||||
typePtr->sParm.t.maxValue = MAXCHAR;
|
||||
} /* end if */
|
||||
|
||||
/* Add some enhanced Pascal standard" types to the symbol table
|
||||
*
|
||||
* string is represent by a 256 byte memory regions consisting of
|
||||
* one byte for the valid string length plus 255 bytes for string
|
||||
* storage
|
||||
*/
|
||||
|
||||
typePtr = addTypeDefine("STRING", sSTRING, sSTRING_SIZE, NULL);
|
||||
if (typePtr)
|
||||
{
|
||||
parentString = typePtr;
|
||||
typePtr->sParm.t.rtype = sRSTRING;
|
||||
typePtr->sParm.t.subType = sCHAR;
|
||||
typePtr->sParm.t.rsize = sRSTRING_SIZE;
|
||||
typePtr->sParm.t.flags = STYPE_VARSIZE;
|
||||
typePtr->sParm.t.minValue = MINCHAR;
|
||||
typePtr->sParm.t.maxValue = MAXCHAR;
|
||||
} /* end if */
|
||||
|
||||
/* Add the standard files to the symbol table */
|
||||
|
||||
(void)addFile("INPUT", 0);
|
||||
(void)addFile("OUTPUT", 0);
|
||||
|
||||
/* Initialize files table */
|
||||
|
||||
for (i = 0; i <= MAX_FILES; i++)
|
||||
{
|
||||
files [i].defined = 0;
|
||||
files [i].flevel = 0;
|
||||
files [i].ftype = 0;
|
||||
files [i].faddr = 0;
|
||||
files [i].fsize = 0;
|
||||
} /* end for */
|
||||
} /* end primeSymbolTable */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
void verifyLabels(int32_t symIndex)
|
||||
{
|
||||
register int16_t i; /* loop index */
|
||||
|
||||
for (i=symIndex; i < nsym; i++)
|
||||
if ((symbolTable[i].sKind == sLABEL)
|
||||
&& (symbolTable[i].sParm.l.unDefined))
|
||||
error (eUNDEFLABEL);
|
||||
} /* end verifyLabels */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
const char noName[] = "********";
|
||||
void dumpTables(void)
|
||||
{
|
||||
register int16_t i;
|
||||
|
||||
fprintf(lstFile,"\nSYMBOL TABLE:\n");
|
||||
fprintf(lstFile,"[ Addr ] NAME KIND LEVL\n");
|
||||
|
||||
for (i = 0; i < nsym; i++)
|
||||
{
|
||||
fprintf(lstFile,"[%08lx] ", (uint32_t)&symbolTable[i]);
|
||||
|
||||
if (symbolTable[i].sName)
|
||||
fprintf(lstFile, "%8s", symbolTable[i].sName);
|
||||
else
|
||||
fprintf(lstFile, "%8s", noName);
|
||||
|
||||
fprintf(lstFile," %04x %04x ",
|
||||
symbolTable[i].sKind,
|
||||
symbolTable[i].sLevel);
|
||||
|
||||
switch (symbolTable[i].sKind)
|
||||
{
|
||||
/* Constants */
|
||||
|
||||
case tINT_CONST :
|
||||
case tCHAR_CONST :
|
||||
case tBOOLEAN_CONST :
|
||||
case tNIL :
|
||||
case sSCALAR :
|
||||
fprintf(lstFile, "val=%ld parent=[%08lx]\n",
|
||||
symbolTable[i].sParm.c.val.i,
|
||||
(unsigned long)symbolTable[i].sParm.c.parent);
|
||||
break;
|
||||
case tREAL_CONST :
|
||||
fprintf(lstFile, "val=%f parent=[%08lx]\n",
|
||||
symbolTable[i].sParm.c.val.f,
|
||||
(unsigned long)symbolTable[i].sParm.c.parent);
|
||||
break;
|
||||
|
||||
/* Types */
|
||||
|
||||
case sTYPE :
|
||||
fprintf(lstFile,
|
||||
"type=%02x rtype=%02x subType=%02x flags=%02x "
|
||||
"asize=%ld rsize=%ld minValue=%ld maxValue=%ld "
|
||||
"parent=[%08lx]\n",
|
||||
symbolTable[i].sParm.t.type,
|
||||
symbolTable[i].sParm.t.rtype,
|
||||
symbolTable[i].sParm.t.subType,
|
||||
symbolTable[i].sParm.t.flags,
|
||||
symbolTable[i].sParm.t.asize,
|
||||
symbolTable[i].sParm.t.rsize,
|
||||
symbolTable[i].sParm.t.minValue,
|
||||
symbolTable[i].sParm.t.maxValue,
|
||||
(unsigned long)symbolTable[i].sParm.t.parent);
|
||||
break;
|
||||
|
||||
/* Procedures/Functions */
|
||||
|
||||
/* Procedures and Functions */
|
||||
|
||||
case sPROC :
|
||||
case sFUNC :
|
||||
fprintf(lstFile,
|
||||
"label=L%04x nParms=%d flags=%02x parent=[%08lx]\n",
|
||||
symbolTable[i].sParm.p.label,
|
||||
symbolTable[i].sParm.p.nParms,
|
||||
symbolTable[i].sParm.p.flags,
|
||||
(unsigned long)symbolTable[i].sParm.p.parent);
|
||||
break;
|
||||
|
||||
/* Labels */
|
||||
|
||||
case sLABEL :
|
||||
fprintf(lstFile, "label=L%04x unDefined=%d\n",
|
||||
symbolTable[i].sParm.l.label,
|
||||
symbolTable[i].sParm.l.unDefined);
|
||||
break;
|
||||
|
||||
/* Files */
|
||||
|
||||
case sFILE :
|
||||
fprintf(lstFile, "fileNumber=%d\n",
|
||||
symbolTable[i].sParm.fileNumber);
|
||||
break;
|
||||
|
||||
/* Variables */
|
||||
|
||||
case sINT :
|
||||
case sBOOLEAN :
|
||||
case sCHAR :
|
||||
case sREAL :
|
||||
case sTEXT :
|
||||
case sARRAY :
|
||||
case sPOINTER :
|
||||
case sVAR_PARM :
|
||||
case sRECORD :
|
||||
case sFILE_OF :
|
||||
fprintf(lstFile, "offset=%ld size=%ld flags=%02x parent=[%08lx]\n",
|
||||
symbolTable[i].sParm.v.offset,
|
||||
symbolTable[i].sParm.v.size,
|
||||
symbolTable[i].sParm.v.flags,
|
||||
(unsigned long)symbolTable[i].sParm.v.parent);
|
||||
break;
|
||||
|
||||
/* Record objects */
|
||||
|
||||
case sRECORD_OBJECT :
|
||||
fprintf(lstFile,
|
||||
"offset=%ld size=%ld record=[%08lx] parent=[%08lx]\n",
|
||||
symbolTable[i].sParm.r.offset,
|
||||
symbolTable[i].sParm.r.size,
|
||||
(unsigned long)symbolTable[i].sParm.r.record,
|
||||
(unsigned long)symbolTable[i].sParm.r.parent);
|
||||
break;
|
||||
|
||||
/* Constant strings */
|
||||
|
||||
case sSTRING_CONST :
|
||||
fprintf(lstFile, "offset=%04lx size=%ld\n",
|
||||
symbolTable[i].sParm.s.offset,
|
||||
symbolTable[i].sParm.s.size);
|
||||
break;
|
||||
|
||||
default :
|
||||
fprintf(lstFile, "Unknown sKind\n");
|
||||
break;
|
||||
|
||||
} /* end switch */
|
||||
} /* end for */
|
||||
|
||||
} /* end dumpTables */
|
||||
#endif
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/***************************************************************************
|
||||
* ptbl.h
|
||||
* External Declarations associated with ptbl.c
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PTBL_H
|
||||
#define __PTBL_H
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
|
||||
/***************************************************************************
|
||||
* Global Variables
|
||||
***************************************************************************/
|
||||
|
||||
extern STYPE *parentInteger;
|
||||
extern STYPE *parentString;
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern const RTYPE *findReservedWord (char *name);
|
||||
extern STYPE *findSymbol (char *inName);
|
||||
extern STYPE *addTypeDefine (char *name, uint8_t type, uint16_t size,
|
||||
STYPE *parent);
|
||||
extern STYPE *addConstant (char *name, uint8_t type, int32_t *value,
|
||||
STYPE *parent);
|
||||
extern STYPE *addStringConst (char *name, uint32_t offset, uint32_t size);
|
||||
extern STYPE *addFile (char *name, uint16_t fileNumber);
|
||||
extern STYPE *addLabel (char *name, uint16_t label);
|
||||
extern STYPE *addProcedure (char *name, uint8_t type, uint16_t label,
|
||||
uint16_t nParms, STYPE *parent);
|
||||
extern STYPE *addVariable (char *name, uint8_t type, uint16_t offset,
|
||||
uint16_t size, STYPE *parent);
|
||||
extern STYPE *addField (char *name, STYPE *record);
|
||||
extern void primeSymbolTable (unsigned long symbolTableSize);
|
||||
extern void verifyLabels (int32_t symIndex);
|
||||
|
||||
#if CONFIG_DEBUG
|
||||
extern void dumpTables (void);
|
||||
#endif
|
||||
|
||||
#endif /* __PTBL_H */
|
||||
@@ -0,0 +1,209 @@
|
||||
/***********************************************************************
|
||||
* ptdefs.h
|
||||
* Token and Symbol Table Definitions
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __PTDEFS_H
|
||||
#define __PTDEFS_H
|
||||
|
||||
/***********************************************************************/
|
||||
/* Token Values 0-0x20 reserved for get_token identification */
|
||||
|
||||
#define tIDENT 0x01
|
||||
#define tINT_CONST 0x02
|
||||
#define tCHAR_CONST 0x03
|
||||
#define tBOOLEAN_CONST 0x04
|
||||
#define tREAL_CONST 0x05
|
||||
#define tSTRING_CONST 0x06
|
||||
|
||||
#define tLE 0x07
|
||||
#define tGE 0x08
|
||||
#define tASSIGN 0x09
|
||||
#define tSUBRANGE 0x0A
|
||||
|
||||
/* Token Values 0x21-0x2F (except 0x24) are for ASCII character tokens */
|
||||
|
||||
#define tNE ('#')
|
||||
#define SQUOTE 0x27
|
||||
#define tMUL ('*')
|
||||
#define tFDIV ('/')
|
||||
|
||||
/* Token Values 0x30-0x39 are spare */
|
||||
/* Token Values 0x3A-0x40 are for ASCII character tokens */
|
||||
|
||||
#define tLT ('<')
|
||||
#define tEQ ('=')
|
||||
#define tGT ('>')
|
||||
|
||||
/* Token Values 0x41-0x5A are SYMBOL TABLE definitions */
|
||||
|
||||
#define sPROC 0x41
|
||||
#define sFUNC 0x42
|
||||
#define sLABEL 0x43
|
||||
#define sTYPE 0x44
|
||||
#define sFILE 0x45
|
||||
#define sINT 0x46
|
||||
#define sBOOLEAN 0x47
|
||||
#define sCHAR 0x48
|
||||
#define sREAL 0x49
|
||||
#define sTEXT 0x4a
|
||||
#define sSTRING 0x4b /* String storage type */
|
||||
#define sRSTRING 0x4c /* String reference type */
|
||||
#define sSTRING_CONST 0x4d
|
||||
#define sPOINTER 0x4e
|
||||
#define sSCALAR 0x4f
|
||||
#define sSCALAR_OBJECT 0x50
|
||||
#define sSUBRANGE 0x51
|
||||
#define sSET_OF 0x52
|
||||
#define sARRAY 0x53
|
||||
#define sRECORD 0x54
|
||||
#define sRECORD_OBJECT 0x55
|
||||
#define sFILE_OF 0x56
|
||||
#define sVAR_PARM 0x57
|
||||
|
||||
/* Token Values 0x5B-0x60 (except 0x5F) are for ASCII character tokens */
|
||||
/* Token Values 0x61-0x7a are SYMBOL TABLE definitions */
|
||||
|
||||
/* Token Values 0x7b-0x7f are for ASCII character tokens */
|
||||
/* Token Value 0x7f is spare */
|
||||
|
||||
/* Token Values 0x80-0xef are for RESERVED WORDS */
|
||||
|
||||
/* Standard constants (TRUE, FALSE, MAXINT) and standard files (INPUT, OUTPUT)
|
||||
* are hard initialized into the constant/symbol table and are transparent
|
||||
* to the compiler */
|
||||
|
||||
/* Reserved Words 0x80-0xaf*/
|
||||
|
||||
#define tAND 0x80
|
||||
#define tARRAY 0x81
|
||||
#define tBEGIN 0x82
|
||||
#define tCASE 0x83
|
||||
#define tCONST 0x84
|
||||
#define tDIV 0x85
|
||||
#define tDO 0x86
|
||||
#define tDOWNTO 0x87
|
||||
#define tELSE 0x88
|
||||
#define tEND 0x89
|
||||
#define tFILE 0x8a
|
||||
#define tFOR 0x8b
|
||||
#define tFUNCTION 0x8c
|
||||
#define tGOTO 0x8d
|
||||
#define tIF 0x8e
|
||||
#define tIMPLEMENTATION 0x08f /* Extended pascal */
|
||||
#define tIN 0x90
|
||||
#define tINTERFACE 0x91 /* Extended pascal */
|
||||
#define tLABEL 0x92
|
||||
#define tMOD 0x93
|
||||
#define tNIL 0x94
|
||||
#define tNOT 0x95
|
||||
#define tOF 0x96
|
||||
#define tOR 0x97
|
||||
#define tPACKED 0x98
|
||||
#define tPROCEDURE 0x99
|
||||
#define tPROGRAM 0x9a
|
||||
#define tRECORD 0x9b
|
||||
#define tREPEAT 0x9c
|
||||
#define tSET 0x9d
|
||||
#define tSHL 0x9e
|
||||
#define tSHR 0x9f
|
||||
#define tTHEN 0xa0
|
||||
#define tTO 0xa1
|
||||
#define tTYPE 0xa2
|
||||
#define tUNIT 0xa3 /* Extended pascal */
|
||||
#define tUNTIL 0xa4
|
||||
#define tUSES 0xa5 /* Extended pascal */
|
||||
#define tVAR 0xa6
|
||||
#define tWHILE 0xa7
|
||||
#define tWITH 0xa8
|
||||
|
||||
/* The following codes indicate that the token is a built-in procedure
|
||||
* or function recognized by the compiler. An additional code will be
|
||||
* place in tknSubType by the tokenizer to indicate which built-in
|
||||
* procedure or function applies.
|
||||
*/
|
||||
|
||||
#define tFUNC 0xb0
|
||||
#define tPROC 0xb1
|
||||
|
||||
/***********************************************************************/
|
||||
/* Codes to indentify built-in functions and procedures */
|
||||
|
||||
#define txNONE 0x00
|
||||
|
||||
/* Standard Functions 0x01-0x1f*/
|
||||
|
||||
#define txABS 0x01
|
||||
#define txARCTAN 0x02
|
||||
#define txCHR 0x03
|
||||
#define txCOS 0x04
|
||||
#define txEOF 0x05
|
||||
#define txEOLN 0x06
|
||||
#define txEXP 0x07
|
||||
#define txLN 0x08
|
||||
#define txODD 0x09
|
||||
#define txORD 0x0a
|
||||
#define txPRED 0x0b
|
||||
#define txROUND 0x0c
|
||||
#define txSIN 0x0d
|
||||
#define txSQR 0x0e
|
||||
#define txSQRT 0x0f
|
||||
#define txSUCC 0x10
|
||||
#define txTRUNC 0x11
|
||||
|
||||
/* "Less than standard" Functions 0x20-0x7f */
|
||||
|
||||
#define txGETENV 0x20
|
||||
|
||||
/* Standard Procedures 0x81-0xbf */
|
||||
|
||||
#define txGET 0x80
|
||||
#define txNEW 0x81
|
||||
#define txPACK 0x82
|
||||
#define txPAGE 0x83
|
||||
#define txPUT 0x84
|
||||
#define txREAD 0x85
|
||||
#define txREADLN 0x86
|
||||
#define txRESET 0x87
|
||||
#define txREWRITE 0x88
|
||||
#define txUNPACK 0x89
|
||||
#define txWRITE 0x8a
|
||||
#define txWRITELN 0x8b
|
||||
|
||||
/* "Less than standard" Procedures 0xc0-0xff */
|
||||
|
||||
#define txVAL 0xc0
|
||||
|
||||
#endif /* __PTDEFS_H */
|
||||
|
||||
@@ -0,0 +1,899 @@
|
||||
/***************************************************************
|
||||
* ptkn.c
|
||||
* Tokenization Package
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
/***************************************************************
|
||||
* Included Functions
|
||||
***************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "pedefs.h"
|
||||
|
||||
#include "pas.h"
|
||||
#include "ptkn.h"
|
||||
#include "ptbl.h"
|
||||
#include "perr.h"
|
||||
|
||||
/***************************************************************
|
||||
* Private Function Prototypes
|
||||
***************************************************************/
|
||||
|
||||
static void getCharacter (void);
|
||||
static void skipLine (void);
|
||||
static bool getLine (void);
|
||||
static void identifier (void);
|
||||
static void string (void);
|
||||
static void unsignedNumber (void);
|
||||
static void unsignedRealNumber (void);
|
||||
static void unsignedExponent (void);
|
||||
static void unsignedHexadecimal (void);
|
||||
static void unsignedBinary (void);
|
||||
|
||||
/***************************************************************
|
||||
* Private Variables
|
||||
***************************************************************/
|
||||
|
||||
static char *strStack; /* String Stack */
|
||||
static uint16_t inChar; /* last gotten character */
|
||||
|
||||
/***************************************************************
|
||||
* Public Variables
|
||||
***************************************************************/
|
||||
|
||||
char *tkn_strt; /* Start of token in string stack */
|
||||
char *stringSP; /* Top of string stack */
|
||||
|
||||
/***************************************************************
|
||||
* Public Functions
|
||||
***************************************************************/
|
||||
|
||||
int16_t primeTokenizer(unsigned long stringStackSize)
|
||||
{
|
||||
TRACE(lstFile,"[primeTokenizer]");
|
||||
|
||||
/* Allocate and initialize the string stack and stack pointers */
|
||||
|
||||
strStack = malloc(stringStackSize);
|
||||
if (!strStack)
|
||||
{
|
||||
fatal(eNOMEMORY);
|
||||
}
|
||||
|
||||
/* Initially, everything points to the bottom of the
|
||||
* string stack.
|
||||
*/
|
||||
|
||||
tkn_strt = strStack;
|
||||
stringSP = strStack;
|
||||
|
||||
/* Set up for input at the initial level of file parsing */
|
||||
|
||||
rePrimeTokenizer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
int16_t rePrimeTokenizer(void)
|
||||
{
|
||||
TRACE(lstFile,"[rePrimeTokenizer]");
|
||||
|
||||
/* (Re-)set the char pointer to the beginning of the line */
|
||||
|
||||
FP->cp = FP->buffer;
|
||||
|
||||
/* Read the next line from the input stream */
|
||||
|
||||
if (!fgets(FP->cp, LINE_SIZE, FP->stream))
|
||||
{
|
||||
/* EOF.. close file */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialize the line nubmer */
|
||||
|
||||
FP->line = 1;
|
||||
|
||||
/* Get the first character from the new file */
|
||||
|
||||
getCharacter();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
/* Tell 'em what what the next character will be (if they should
|
||||
* choose to get it). This is similar to getCharacter(), except that
|
||||
* the character pointer is not incremented past the character. The
|
||||
* next time that getCharacter() is called, it will get the character
|
||||
* again.
|
||||
*/
|
||||
|
||||
char getNextCharacter(bool skipWhiteSpace)
|
||||
{
|
||||
/* Get the next character from the line buffer. */
|
||||
|
||||
inChar = *(FP->cp);
|
||||
|
||||
/* If it is the EOL then read the next line from the input file */
|
||||
|
||||
if (!inChar)
|
||||
{
|
||||
/* We have used all of the characters on this line. Read the next
|
||||
* line of data
|
||||
*/
|
||||
|
||||
if (getLine())
|
||||
{
|
||||
/* Uh-oh, we are out of data! Just return some bogus value. */
|
||||
inChar = '?';
|
||||
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
/* Otherwise, recurse to try again. */
|
||||
|
||||
return getNextCharacter(skipWhiteSpace);
|
||||
|
||||
} /* end else */
|
||||
} /* end if */
|
||||
|
||||
/* If it is a space and we have been told to skip spaces then consume
|
||||
* the input line until a non-space or the EOL is encountered.
|
||||
*/
|
||||
|
||||
else if (skipWhiteSpace)
|
||||
{
|
||||
while ((isspace(inChar)) && (inChar))
|
||||
{
|
||||
/* Skip over the space */
|
||||
|
||||
(FP->cp)++;
|
||||
|
||||
/* A get the character after the space */
|
||||
|
||||
inChar = *(FP->cp);
|
||||
|
||||
} /* end while */
|
||||
|
||||
/* If we hit the EOL while searching for the next non-space, then
|
||||
* recurse to try again on the next line
|
||||
*/
|
||||
|
||||
if (!inChar)
|
||||
{
|
||||
return getNextCharacter(skipWhiteSpace);
|
||||
}
|
||||
} /* end else if */
|
||||
|
||||
return inChar;
|
||||
|
||||
} /* end getNextCharacter */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
void getToken(void)
|
||||
{
|
||||
/* Skip over leading spaces and comments */
|
||||
|
||||
while (isspace(inChar)) getCharacter();
|
||||
|
||||
/* Point to the beginning of the next token */
|
||||
|
||||
tkn_strt = stringSP;
|
||||
|
||||
/* Process Identifier, Symbol, or Reserved Word */
|
||||
|
||||
if ((isalpha(inChar)) || (inChar == '_'))
|
||||
identifier();
|
||||
|
||||
/* Process Numeric */
|
||||
|
||||
else if (isdigit(inChar))
|
||||
unsignedNumber();
|
||||
|
||||
/* Process string */
|
||||
|
||||
else if (inChar == SQUOTE)
|
||||
string(); /* process string type */
|
||||
|
||||
/* Process ':' or assignment */
|
||||
|
||||
else if (inChar == ':')
|
||||
{
|
||||
getCharacter();
|
||||
if (inChar == '=') {token = tASSIGN; getCharacter();}
|
||||
else token = ':';
|
||||
} /* end else if */
|
||||
|
||||
/* Process '.' or subrange or real-number */
|
||||
|
||||
else if (inChar == '.')
|
||||
{
|
||||
/* Get the character after the '.' */
|
||||
|
||||
getCharacter();
|
||||
|
||||
/* ".." indicates a subrange */
|
||||
|
||||
if (inChar == '.')
|
||||
{
|
||||
token = tSUBRANGE;
|
||||
getCharacter();
|
||||
}
|
||||
|
||||
/* '.' digit is a real number */
|
||||
|
||||
else if (isdigit(inChar))
|
||||
unsignedRealNumber();
|
||||
|
||||
/* Otherwise, it is just a '.' */
|
||||
|
||||
else token = '.';
|
||||
} /* end else if */
|
||||
|
||||
/* Process '<' or '<=' or '<>' or '<<' */
|
||||
|
||||
else if (inChar == '<')
|
||||
{
|
||||
getCharacter();
|
||||
if (inChar == '>') {token = tNE; getCharacter();}
|
||||
else if (inChar == '=') {token = tLE; getCharacter();}
|
||||
else if (inChar == '<') {token = tSHL; getCharacter();}
|
||||
else token = tLT;
|
||||
} /* end else if */
|
||||
|
||||
/* Process '>' or '>=' or '><' or '>>' */
|
||||
|
||||
else if (inChar == '>')
|
||||
{
|
||||
getCharacter();
|
||||
if (inChar == '<') {token = tNE; getCharacter();}
|
||||
else if (inChar == '=') {token = tGE; getCharacter();}
|
||||
else if (inChar == '>') {token = tSHR; getCharacter();}
|
||||
else token = tGT;
|
||||
} /* end else if */
|
||||
|
||||
/* Get Comment -- form { .. } */
|
||||
|
||||
else if (inChar == '{')
|
||||
{
|
||||
do getCharacter(); /* get the next character */
|
||||
while (inChar != '}'); /* loop until end of comment */
|
||||
getCharacter(); /* skip over end of comment */
|
||||
getToken(); /* get the next real token */
|
||||
} /* end else if */
|
||||
|
||||
/* Get comment -- form (* .. *) */
|
||||
|
||||
else if (inChar == '(')
|
||||
{
|
||||
getCharacter(); /* skip over comment character */
|
||||
if (inChar != '*') /* is this a comment? */
|
||||
{
|
||||
token = '('; /* No return '(' leaving the
|
||||
* unprocessed char in inChar */
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t lastChar = ' '; /* YES... prime the look behind */
|
||||
for (;;) /* look for end of comment */
|
||||
{
|
||||
getCharacter(); /* get the next character */
|
||||
if ((lastChar == '*') && /* Is it '*)' ? */
|
||||
(inChar == ')'))
|
||||
{
|
||||
break; /* Yes... break out */
|
||||
}
|
||||
lastChar = inChar; /* save the last character */
|
||||
} /* end for */
|
||||
|
||||
getCharacter(); /* skip over the comment end char */
|
||||
getToken(); /* and get the next real token */
|
||||
} /* end else */
|
||||
} /* end else if */
|
||||
|
||||
/* NONSTANDARD: All C/C++-style comments */
|
||||
|
||||
else if (inChar == '/')
|
||||
{
|
||||
getCharacter(); /* skip over comment character */
|
||||
if (inChar == '/') /* C++ style comment? */
|
||||
{
|
||||
skipLine(); /* Yes, skip rest of line */
|
||||
getToken(); /* and get the next real token */
|
||||
}
|
||||
else if (inChar != '*') /* is this a C-style comment? */
|
||||
{
|
||||
token = '/'; /* No return '/' leaving the
|
||||
* unprocessed char in inChar */
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t lastChar = ' '; /* YES... prime the look behind */
|
||||
for (;;) /* look for end of comment */
|
||||
{
|
||||
getCharacter(); /* get the next character */
|
||||
if ((lastChar == '*') && /* Is it '*)' ? */
|
||||
(inChar == '/'))
|
||||
{
|
||||
break; /* Yes... break out */
|
||||
}
|
||||
lastChar = inChar; /* save the last character */
|
||||
} /* end for */
|
||||
|
||||
getCharacter(); /* skip over the comment end char */
|
||||
getToken(); /* and get the next real token */
|
||||
} /* end else */
|
||||
} /* end else if */
|
||||
|
||||
/* Check for $XXXX (hex) */
|
||||
|
||||
else if (inChar == '%')
|
||||
unsignedHexadecimal();
|
||||
|
||||
/* Check for $BBBB (binary) */
|
||||
|
||||
else if (inChar == '%')
|
||||
unsignedBinary();
|
||||
|
||||
/* if inChar is an ASCII character then return token = character */
|
||||
|
||||
else if (isascii(inChar))
|
||||
{
|
||||
token = inChar;
|
||||
getCharacter();
|
||||
} /* end else if */
|
||||
|
||||
/* Otherwise, discard the character and try again */
|
||||
|
||||
else
|
||||
{
|
||||
getCharacter();
|
||||
getToken();
|
||||
} /* end else */
|
||||
|
||||
DEBUG(lstFile,"[%02x]", token);
|
||||
|
||||
} /* End getToken */
|
||||
|
||||
/***************************************************************
|
||||
* Private Functions
|
||||
***************************************************************/
|
||||
|
||||
static void identifier(void)
|
||||
{
|
||||
const RTYPE *rptr; /* Pointer to reserved word */
|
||||
|
||||
tknSubType = txNONE; /* Initialize */
|
||||
|
||||
/* Concatenate identifier */
|
||||
|
||||
do
|
||||
{
|
||||
*stringSP++ = toupper(inChar); /* concatenate char */
|
||||
getCharacter(); /* get next character */
|
||||
}
|
||||
while ((isalnum(inChar)) || (inChar == '_'));
|
||||
*stringSP++ = '\0'; /* make ASCIIZ string */
|
||||
|
||||
/* Check if the identifier is a reserved word */
|
||||
|
||||
rptr = findReservedWord(tkn_strt);
|
||||
if (rptr)
|
||||
{
|
||||
token = rptr->rtype; /* get type from rsw table */
|
||||
tknSubType = rptr->subtype; /* get subtype from rsw table */
|
||||
stringSP = tkn_strt; /* pop token from stack */
|
||||
} /* End if */
|
||||
|
||||
/* Check if the identifier is a symbol */
|
||||
|
||||
else
|
||||
{
|
||||
tknPtr = findSymbol(tkn_strt);
|
||||
if (tknPtr)
|
||||
{
|
||||
token = tknPtr->sKind; /* get type from symbol table */
|
||||
stringSP = tkn_strt; /* pop token from stack */
|
||||
|
||||
/* The following assignments only apply to constants. However it
|
||||
* is simpler just to make the assignments than it is to determine
|
||||
* if is appropriate to do so
|
||||
*/
|
||||
|
||||
if (token == tREAL_CONST)
|
||||
tknReal = tknPtr->sParm.c.val.f;
|
||||
else
|
||||
tknInt = tknPtr->sParm.c.val.i;
|
||||
} /* End if */
|
||||
|
||||
/* Otherwise, the token is an identifier */
|
||||
else
|
||||
token = tIDENT;
|
||||
|
||||
} /* end else */
|
||||
|
||||
} /* End identifier */
|
||||
|
||||
/***************************************************************/
|
||||
/* Process string */
|
||||
|
||||
static void string(void)
|
||||
{
|
||||
register int16_t count = 0; /* # chars in string */
|
||||
|
||||
token = tSTRING_CONST; /* indicate string constant type */
|
||||
getCharacter(); /* skip over 1st single quote */
|
||||
|
||||
while (inChar != SQUOTE) /* loop until next single quote */
|
||||
{
|
||||
if (inChar == '\n') /* check for EOL in string */
|
||||
{
|
||||
error(eNOSQUOTE); /* ERROR, terminate string */
|
||||
break;
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
*stringSP++ = inChar; /* concatenate character */
|
||||
count++; /* bump count of chars */
|
||||
} /* end else */
|
||||
getCharacter(); /* get the next character */
|
||||
} /* end while */
|
||||
*stringSP++ = '\0'; /* terminate ASCIIZ string */
|
||||
|
||||
getCharacter(); /* skip over last single quote */
|
||||
if (count == 1) /* Check for char constant */
|
||||
{
|
||||
token = tCHAR_CONST; /* indicate char constant type */
|
||||
tknInt = *tkn_strt; /* (integer) value = single char */
|
||||
stringSP = tkn_strt; /* "pop" from string stack */
|
||||
} /* end if */
|
||||
} /* end string */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void getCharacter(void)
|
||||
{
|
||||
/* Get the next character from the line buffer. If EOL, get next line */
|
||||
|
||||
inChar = *(FP->cp)++;
|
||||
if (!inChar)
|
||||
{
|
||||
/* We have used all of the characters on this line. Read the next
|
||||
* line of data
|
||||
*/
|
||||
|
||||
skipLine();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void skipLine(void)
|
||||
{
|
||||
if (getLine())
|
||||
{
|
||||
/* Uh-oh, we are out of data! Just return some bogus value. */
|
||||
|
||||
inChar = '?';
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
/* Otherwise, get the first character from the line */
|
||||
|
||||
getCharacter();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static bool getLine(void)
|
||||
{
|
||||
bool endOfFile = false;
|
||||
|
||||
/* Reset the character pointer to the start of the new line */
|
||||
|
||||
FP->cp = FP->buffer;
|
||||
|
||||
/* Read the next line from the currently active file */
|
||||
|
||||
if (!fgets(FP->cp, LINE_SIZE, FP->stream))
|
||||
{
|
||||
/* We are at an EOF for this file. Check if we are processing an
|
||||
* included file
|
||||
*/
|
||||
|
||||
if (includeIndex > 0)
|
||||
{
|
||||
/* Yes. Close the file */
|
||||
|
||||
closeNestedFile();
|
||||
|
||||
/* Indicate that there is no data on the input line. NOTE:
|
||||
* that FP now refers to the previous file at the next lower
|
||||
* level of nesting.
|
||||
*/
|
||||
|
||||
FP->buffer[0] = '\0';
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
/* No. We are completely out of data. Return true in this case. */
|
||||
|
||||
endOfFile = true;
|
||||
} /* end else */
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
/* We have a new line of data. Increment the line number, then echo
|
||||
* the new line to the list file.
|
||||
*/
|
||||
|
||||
(FP->line)++;
|
||||
fprintf(lstFile, "%d:%04ld %s", FP->include, FP->line, FP->buffer);
|
||||
} /* end else */
|
||||
|
||||
return endOfFile;
|
||||
|
||||
} /* end getLine */
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void unsignedNumber(void)
|
||||
{
|
||||
/* This logic (along with with unsignedRealNumber, and
|
||||
* unsignedRealExponent) handles:
|
||||
*
|
||||
* FORM: integer-number = decimal-integer | hexadecimal-integer |
|
||||
* binary-integer
|
||||
* FORM: decimal-integer = digit-sequence
|
||||
* FORM: real-number =
|
||||
* digit-sequence '.' [digit-sequence] [ exponent scale-factor ] |
|
||||
* '.' digit-sequence [ exponent scale-factor ] |
|
||||
* digit-sequence exponent scale-factor
|
||||
* FORM: exponent = 'e' | 'E'
|
||||
*
|
||||
* When called, inChar is equal to the leading digit of a
|
||||
* digit-sequence. NOTE that the real-number form beginning with
|
||||
* '.' does not use this logic.
|
||||
*/
|
||||
|
||||
/* Assume an integer type (might be real) */
|
||||
|
||||
token = tINT_CONST;
|
||||
|
||||
/* Concatenate all digits until an non-digit is found */
|
||||
|
||||
do
|
||||
{
|
||||
*stringSP++ = inChar;
|
||||
getCharacter();
|
||||
}
|
||||
while (isdigit(inChar));
|
||||
|
||||
/* If it is a digit-sequence followed by 'e' (or 'E'), then
|
||||
* continue processing this token as a real number.
|
||||
*/
|
||||
|
||||
if ((inChar == 'e') || (inChar == 'E'))
|
||||
{
|
||||
unsignedExponent();
|
||||
}
|
||||
|
||||
/* If the digit-sequence is followed by '.' but not by ".." (i.e.,
|
||||
* this is not a subrange), then switch we are parsing a real time.
|
||||
* Otherwise, convert the integer string to binary.
|
||||
*/
|
||||
|
||||
else if ((inChar != '.') || (getNextCharacter(false) == '.'))
|
||||
{
|
||||
/* Terminate the integer string and convert it using sscanf */
|
||||
|
||||
*stringSP++ = '\0';
|
||||
(void)sscanf(tkn_strt, "%ld", &tknInt);
|
||||
|
||||
/* Remove the integer string from the character identifer stack */
|
||||
|
||||
stringSP = tkn_strt;
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
/* Its a real value! Now really get the next character and
|
||||
* after the decimal point (this will work whether or not
|
||||
* getNextCharacter() was called). Then process the real number.
|
||||
*/
|
||||
|
||||
getCharacter();
|
||||
unsignedRealNumber();
|
||||
} /* end if */
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void unsignedRealNumber(void)
|
||||
{
|
||||
/* This logic (along with with unsignedNumber and unsignedExponent)
|
||||
* handles:
|
||||
*
|
||||
* FORM: real-number =
|
||||
* digit-sequence '.' [digit-sequence] [ exponent scale-factor ] |
|
||||
* '.' digit-sequence [ exponent scale-factor ] |
|
||||
* digit-sequence exponent scale-factor
|
||||
* FORM: exponent = 'e' | 'E'
|
||||
*
|
||||
* When called:
|
||||
* - inChar is the character AFTER the '.'.
|
||||
* - Any leading digit-sequence is already in the character stack
|
||||
* - the '.' is not in the character stack.
|
||||
*/
|
||||
|
||||
/* Its a real constant */
|
||||
|
||||
token = tREAL_CONST;
|
||||
|
||||
/* Save the decimal point (inChar points to the character after
|
||||
* the decimal point).
|
||||
*/
|
||||
|
||||
*stringSP++ = '.';
|
||||
|
||||
/* Now, loop to process the optional digit-sequence after the
|
||||
* decimal point.
|
||||
*/
|
||||
|
||||
while (isdigit(inChar))
|
||||
{
|
||||
*stringSP++ = inChar;
|
||||
getCharacter();
|
||||
}
|
||||
|
||||
/* If it is a digit-sequence followed by 'e' (or 'E'), then
|
||||
* continue processing this token as a real number.
|
||||
*/
|
||||
|
||||
if ((inChar == 'e') || (inChar == 'E'))
|
||||
{
|
||||
unsignedExponent();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There is no exponent...
|
||||
* Terminate the real number string and convert it to binay
|
||||
* using sscanf.
|
||||
*/
|
||||
|
||||
*stringSP++ = '\0';
|
||||
(void) sscanf(tkn_strt, "%lf", &tknReal);
|
||||
} /* end if */
|
||||
|
||||
/* Remove the number string from the character identifer stack */
|
||||
|
||||
stringSP = tkn_strt;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void unsignedExponent(void)
|
||||
{
|
||||
/* This logic (along with with unsignedNumber and unsignedRealNumber)
|
||||
* handles:
|
||||
*
|
||||
* FORM: real-number =
|
||||
* digit-sequence '.' [digit-sequence] [ exponent scale-factor ] |
|
||||
* '.' digit-sequence [ exponent scale-factor ] |
|
||||
* digit-sequence exponent scale-factor
|
||||
* FORM: exponent = 'e'
|
||||
* FORM: scale-factor = [ sign ] digit-sequence
|
||||
*
|
||||
* When called:
|
||||
* - inChar holds the 'E' (or 'e') exponent
|
||||
* - Any leading digit-sequences or decimal points are already in the
|
||||
* character stack
|
||||
* - the 'E' (or 'e') is not in the character stack.
|
||||
*/
|
||||
|
||||
/* Its a real constant */
|
||||
|
||||
token = tREAL_CONST;
|
||||
|
||||
/* Save the decimal point (inChar points to the character after
|
||||
* the decimal point).
|
||||
*/
|
||||
|
||||
*stringSP++ = inChar;
|
||||
getCharacter();
|
||||
|
||||
/* Check for an optional sign before the exponent value */
|
||||
|
||||
if ((inChar == '-') || (inChar == '+'))
|
||||
{
|
||||
/* Add the sign to the stack */
|
||||
|
||||
*stringSP++ = inChar;
|
||||
getCharacter();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add a '+' sign to the stack */
|
||||
|
||||
*stringSP++ = '+';
|
||||
}
|
||||
|
||||
/* A digit sequence must appear after the exponent and optional
|
||||
* sign.
|
||||
*/
|
||||
|
||||
if (!isdigit(inChar))
|
||||
{
|
||||
error(eEXPONENT);
|
||||
tknReal = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now, loop to process the required digit-sequence */
|
||||
|
||||
do
|
||||
{
|
||||
*stringSP++ = inChar;
|
||||
getCharacter();
|
||||
}
|
||||
while (isdigit(inChar));
|
||||
|
||||
/* Terminate the real number string and convert it to binay
|
||||
* using sscanf.
|
||||
*/
|
||||
|
||||
*stringSP++ = '\0';
|
||||
(void) sscanf(tkn_strt, "%lf", &tknReal);
|
||||
}
|
||||
|
||||
/* Remove the number string from the character identifer stack */
|
||||
|
||||
stringSP = tkn_strt;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void unsignedHexadecimal(void)
|
||||
{
|
||||
/* FORM: integer-number = decimal-integer | hexadecimal-integer |
|
||||
* binary-integer
|
||||
* FORM: hexadecimal-integer = '$' hex-digit-sequence
|
||||
* FORM: hex-digit-sequence = hex-digit { hex-digit }
|
||||
* FORM: hex-digit = digit | 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
|
||||
*
|
||||
* On entry, inChar is '$'
|
||||
*/
|
||||
|
||||
/* This is another representation for an integer */
|
||||
|
||||
token = tINT_CONST;
|
||||
|
||||
/* Loop to process each hex 'digit' */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Get the next character */
|
||||
|
||||
getCharacter();
|
||||
|
||||
/* Is it a decimal digit? */
|
||||
|
||||
if (isdigit(inChar))
|
||||
*stringSP++ = inChar;
|
||||
|
||||
/* Is it a hex 'digit'? */
|
||||
|
||||
else if ((inChar >= 'A') && (inChar <= 'F'))
|
||||
*stringSP++ = inChar;
|
||||
|
||||
else if ((inChar >= 'a') && (inChar <= 'f'))
|
||||
*stringSP++ = _toupper(inChar);
|
||||
|
||||
/* Otherwise, that must be the end of the hex value */
|
||||
|
||||
else break;
|
||||
}
|
||||
|
||||
/* Terminate the hex string and convert to binary using sscanf */
|
||||
|
||||
*stringSP++ = '\0';
|
||||
(void)sscanf(tkn_strt, "%lx", &tknInt);
|
||||
|
||||
/* Remove the hex string from the character identifer stack */
|
||||
|
||||
stringSP = tkn_strt;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
|
||||
static void unsignedBinary(void)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
/* FORM: integer-number = decimal-integer | hexadecimal-integer |
|
||||
* binary-integer
|
||||
* FORM: binary-integer = '%' binary-digit-sequence
|
||||
* FORM: binary-digit-sequence = binary-digit { binary-digit }
|
||||
* FORM: binary-digit = '0' | '1'
|
||||
*
|
||||
* On entry, inChar is '%'
|
||||
*/
|
||||
|
||||
/* This is another representation for an integer */
|
||||
|
||||
token = tINT_CONST;
|
||||
|
||||
/* Loop to process each hex 'digit' */
|
||||
|
||||
value = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Get the next character */
|
||||
|
||||
getCharacter();
|
||||
|
||||
/* Is it a binary 'digit'? */
|
||||
|
||||
if (inChar == '0')
|
||||
value <<= 1;
|
||||
|
||||
else if (inChar == '1')
|
||||
{
|
||||
value <<= 1;
|
||||
value |= 1;
|
||||
}
|
||||
|
||||
/* Otherwise, that must be the end of the binary value */
|
||||
|
||||
else break;
|
||||
}
|
||||
|
||||
/* I don't there there is an sscanf conversion for binary, that's
|
||||
* why we did it above.
|
||||
*/
|
||||
|
||||
tknInt = (int32_t)value;
|
||||
}
|
||||
|
||||
/***************************************************************/
|
||||
@@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
* ptkn.h
|
||||
* External Declarations associated with ptkn.c
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PTKN_H
|
||||
#define __PTKN_H
|
||||
|
||||
/***************************************************************************
|
||||
* Included Files
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/***************************************************************************
|
||||
* Public Variables
|
||||
***************************************************************************/
|
||||
|
||||
/* String stack access variables */
|
||||
|
||||
extern char *tkn_strt; /* Start of token in string stack */
|
||||
extern char *stringSP; /* Top of string stack */
|
||||
|
||||
/***************************************************************************
|
||||
* Public Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void getToken (void);
|
||||
extern char getNextCharacter (bool skipWhiteSpace);
|
||||
extern int16_t primeTokenizer (unsigned long stringStackSize);
|
||||
extern int16_t rePrimeTokenizer (void);
|
||||
|
||||
#endif /* __PTKN_H */
|
||||
@@ -0,0 +1,599 @@
|
||||
/**********************************************************************
|
||||
* punit.c
|
||||
* Parse a pascal unit file
|
||||
*
|
||||
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* Included Files
|
||||
**********************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "keywords.h"
|
||||
#include "pasdefs.h"
|
||||
#include "ptdefs.h"
|
||||
#include "podefs.h"
|
||||
#include "pedefs.h"
|
||||
#include "poff.h" /* FHT_ definitions */
|
||||
|
||||
#include "pas.h" /* for globals */
|
||||
#include "pblck.h" /* for block(), constantDefinitionGroup(), etc. */
|
||||
#include "pgen.h" /* for pas_Generate*() */
|
||||
#include "ptkn.h" /* for getToken() */
|
||||
#include "ptbl.h" /* for addFile() */
|
||||
#include "pofflib.h" /* For poff*() functions*/
|
||||
#include "perr.h" /* for error() */
|
||||
#include "pprgm.h" /* for usesSection() */
|
||||
#include "punit.h"
|
||||
|
||||
/***********************************************************************
|
||||
* Pre-processor Definitions
|
||||
***********************************************************************/
|
||||
|
||||
#define intAlign(x) (((x) + (sINT_SIZE-1)) & (~(sINT_SIZE-1)))
|
||||
|
||||
/***********************************************************************
|
||||
* Private Function Prototypes
|
||||
***********************************************************************/
|
||||
|
||||
static void interfaceSection (void);
|
||||
static void exportedProcedureHeading (void);
|
||||
static void exportedFunctionHeading (void);
|
||||
|
||||
/***********************************************************************
|
||||
* Global Functions
|
||||
***********************************************************************/
|
||||
/* This function is called only main() when the first token parsed out
|
||||
* the specified file is 'unit'. In this case, we are parsing a unit file
|
||||
* and generating a unit binary.
|
||||
*/
|
||||
|
||||
void unitImplementation(void)
|
||||
{
|
||||
char *saveTknStart = tkn_strt;
|
||||
|
||||
TRACE(lstFile, "[unitImplementation]");
|
||||
|
||||
/* FORM: unit =
|
||||
* unit-heading ';' interface-section implementation-section
|
||||
* init-section '.'
|
||||
* FORM: unit-heading = 'unit' identifer
|
||||
* FORM: interface-section =
|
||||
* 'interface' [ uses-section ] interface-declaration
|
||||
* FORM: implementation-section =
|
||||
* 'implementation' [ uses-section ] declaration-group
|
||||
* FORM: init-section =
|
||||
* 'initialization statement-sequence
|
||||
* ['finalization' statement-sequence] 'end' |
|
||||
* compound-statement | 'end'
|
||||
*
|
||||
* On entry, the 'unit' keyword has already been parsed. The
|
||||
* current token should point to the identifier following unit.
|
||||
*/
|
||||
|
||||
/* Skip over the unit identifier (the caller has already verified
|
||||
* that we are processing the correct unit).
|
||||
*/
|
||||
|
||||
if (token != tIDENT) error(eIDENT);
|
||||
|
||||
/* Set a UNIT indication in the output poff file header */
|
||||
|
||||
poffSetFileType(poffHandle, FHT_UNIT, 0, tkn_strt);
|
||||
poffSetArchitecture(poffHandle, FHA_PCODE);
|
||||
|
||||
/* Discard the unit name and get the next token */
|
||||
|
||||
stringSP = saveTknStart;
|
||||
getToken();
|
||||
|
||||
/* Skip over the semicolon separating the unit-heading from the
|
||||
* interface-section.
|
||||
*/
|
||||
|
||||
if (token != ';') error(eSEMICOLON);
|
||||
else getToken();
|
||||
|
||||
/* Verify that the interface-section is present
|
||||
* FORM: interface-section =
|
||||
* 'interface' [ uses-section ] interface-declaration
|
||||
*/
|
||||
|
||||
interfaceSection();
|
||||
|
||||
/* Verify that the implementation section is present
|
||||
* FORM: implementation-section =
|
||||
* 'implementation' [ uses-section ] declaration-group
|
||||
*/
|
||||
|
||||
if (token != tIMPLEMENTATION) error(eIMPLEMENTATION);
|
||||
else getToken();
|
||||
|
||||
FP->section = eIsImplementationSection;
|
||||
|
||||
/* Check for the presence of an optional uses-section */
|
||||
|
||||
if (token == tUSES)
|
||||
{
|
||||
/* Process the uses-section */
|
||||
|
||||
getToken();
|
||||
usesSection();
|
||||
}
|
||||
|
||||
/* Now, process the declaration-group
|
||||
*
|
||||
* FORM: implementation-section =
|
||||
* 'implementation' [ uses-section ] declaration-group
|
||||
* FORM: init-section =
|
||||
* 'initialization statement-sequence
|
||||
* ['finalization' statement-sequence] 'end' |
|
||||
* compound-statement | 'end'
|
||||
*/
|
||||
|
||||
declarationGroup(0);
|
||||
|
||||
/* Process the init-section
|
||||
* FORM: init-section =
|
||||
* 'initialization statement-sequence
|
||||
* ['finalization' statement-sequence] 'end' |
|
||||
* compound-statement | 'end'
|
||||
*
|
||||
* Not yet... for now, we only require the 'end'
|
||||
*/
|
||||
|
||||
FP->section = eIsInitializationSection;
|
||||
if (token != tEND) error(eEND);
|
||||
else getToken();
|
||||
|
||||
FP->section = eIsOtherSection;
|
||||
|
||||
/* Verify that the unit file ends with a period */
|
||||
|
||||
if (token != '.') error(ePERIOD);
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* This logic is called from usersSection after any a uses-section is
|
||||
* encountered in any file at any level. In this case, we are only
|
||||
* going to parse the interface section from the unit file.
|
||||
*/
|
||||
|
||||
void unitInterface(void)
|
||||
{
|
||||
int32_t savedDStack = dstack;
|
||||
TRACE(lstFile, "[unitInterface]");
|
||||
|
||||
/* FORM: unit =
|
||||
* unit-heading ';' interface-section implementation-section
|
||||
* init-section
|
||||
* FORM: unit-heading = 'unit' identifer
|
||||
*
|
||||
* On entry, the 'unit' keyword has already been parsed. The
|
||||
* current token should point to the identifier following unit.
|
||||
*/
|
||||
|
||||
/* Skip over the unit identifier (the caller has already verified
|
||||
* that we are processing the correct unit).
|
||||
*/
|
||||
|
||||
if (token != tIDENT) error(eIDENT);
|
||||
else getToken();
|
||||
|
||||
/* Skip over the semicolon separating the unit-heading from the
|
||||
* interface-section.
|
||||
*/
|
||||
|
||||
if (token != ';') error(eSEMICOLON);
|
||||
else getToken();
|
||||
|
||||
/* Process the interface-section
|
||||
* FORM: interface-section =
|
||||
* 'interface' [ uses-section ] interface-declaration
|
||||
*/
|
||||
|
||||
interfaceSection();
|
||||
|
||||
/* Verify that the implementation section is present
|
||||
* FORM: implementation-section =
|
||||
* 'implementation' [ uses-section ] declaration-group
|
||||
*/
|
||||
|
||||
if (token != tIMPLEMENTATION) error(eIMPLEMENTATION);
|
||||
|
||||
/* Then just ignore the rest of the file. We'll let the compilation
|
||||
* of the unit file check the correctness of the implementation.
|
||||
*/
|
||||
|
||||
FP->section = eIsOtherSection;
|
||||
|
||||
/* If we are generating a program binary, then all variables declared
|
||||
* by this logic a bonafide. But if are generating UNIT binary, then
|
||||
* all variables declared as imported with a relative stack offset.
|
||||
* In this case, we must release any data stack allocated in this
|
||||
* process.
|
||||
*/
|
||||
|
||||
dstack = savedDStack;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Private Functions
|
||||
***********************************************************************/
|
||||
|
||||
static void interfaceSection(void)
|
||||
{
|
||||
int16_t saveNSym = nsym; /* Save top of symbol table */
|
||||
int16_t saveNConst = nconst; /* Save top of constant table */
|
||||
|
||||
TRACE(lstFile, "[interfaceSection]");
|
||||
|
||||
/* FORM: interface-section =
|
||||
* 'interface' [ uses-section ] interface-declaration
|
||||
*
|
||||
* On entry, the unit-heading keyword has already been parsed. The
|
||||
* current token should point to the identifier following unit.
|
||||
*/
|
||||
|
||||
if (token != tINTERFACE) error(eINTERFACE);
|
||||
else getToken();
|
||||
|
||||
FP->section = eIsInterfaceSection;
|
||||
|
||||
/* Check for the presence of an optional uses-section */
|
||||
|
||||
if (token == tUSES)
|
||||
{
|
||||
/* Process the uses-section */
|
||||
|
||||
getToken();
|
||||
usesSection();
|
||||
}
|
||||
|
||||
/* Process the interface-declaration
|
||||
*
|
||||
* FORM: interface-declaration =
|
||||
* [ constant-definition-group ] [ type-definition-group ]
|
||||
* [ variable-declaration-group ] exported-heading
|
||||
*/
|
||||
|
||||
/* Process optional constant-definition-group.
|
||||
* FORM: constant-definition-group =
|
||||
* 'const' constant-definition ';' { constant-definition ';' }
|
||||
*/
|
||||
|
||||
if (token == tCONST)
|
||||
{
|
||||
const_strt = saveNConst; /* Limit search to present level */
|
||||
getToken(); /* Get identifier */
|
||||
const_strt = 0;
|
||||
|
||||
/* Process constant-definition.
|
||||
* FORM: constant-definition = identifier '=' constant
|
||||
*/
|
||||
|
||||
constantDefinitionGroup();
|
||||
|
||||
} /* end if */
|
||||
|
||||
/* Process type-definition-group
|
||||
* FORM: type-definition-group =
|
||||
* 'type' type-definition ';' { type-definition ';' }
|
||||
*/
|
||||
|
||||
if (token == tTYPE)
|
||||
{
|
||||
const_strt = saveNConst; /* Limit search to present level */
|
||||
sym_strt = saveNSym;
|
||||
getToken(); /* Get identifier */
|
||||
const_strt = 0;
|
||||
sym_strt = 0;
|
||||
|
||||
/* Process the type-definitions in the type-definition-group
|
||||
* FORM: type-definition = identifier '=' type-denoter
|
||||
*/
|
||||
|
||||
typeDefinitionGroup();
|
||||
} /* end if */
|
||||
|
||||
/* Process the optional variable-declaration-group
|
||||
* FORM: variable-declaration-group =
|
||||
* 'var' variable-declaration { ';' variable-declaration }
|
||||
*/
|
||||
|
||||
if (token == tVAR)
|
||||
{
|
||||
const_strt = saveNConst; /* Limit search to present level */
|
||||
sym_strt = saveNSym;
|
||||
getToken(); /* Get identifier */
|
||||
const_strt = 0;
|
||||
sym_strt = 0;
|
||||
|
||||
/* Process the variable declarations
|
||||
* FORM: variable-declaration = identifier-list ':' type-denoter
|
||||
* FORM: identifier-list = identifier { ',' identifier }
|
||||
*/
|
||||
|
||||
variableDeclarationGroup();
|
||||
} /* end if */
|
||||
|
||||
/* Process the exported-heading
|
||||
*
|
||||
* FORM: exported-heading =
|
||||
* procedure-heading ';' [ directive ] |
|
||||
* function-heading ';' [ directive ]
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* FORM: function-heading =
|
||||
* 'function' function-identifier [ formal-parameter-list ]
|
||||
* ':' result-type
|
||||
*/
|
||||
|
||||
if (token == tFUNCTION)
|
||||
{
|
||||
const_strt = saveNConst; /* Limit search to present level */
|
||||
sym_strt = saveNSym;
|
||||
getToken(); /* Get identifier */
|
||||
const_strt = 0;
|
||||
sym_strt = 0;
|
||||
|
||||
/* Process the interface declaration */
|
||||
|
||||
exportedFunctionHeading();
|
||||
} /* end if */
|
||||
|
||||
/* FORM: procedure-heading =
|
||||
* 'procedure' procedure-identifier [ formal-parameter-list ]
|
||||
*/
|
||||
|
||||
else if (token == tPROCEDURE)
|
||||
{
|
||||
const_strt = saveNConst; /* Limit search to present level */
|
||||
sym_strt = saveNSym;
|
||||
getToken(); /* Get identifier */
|
||||
const_strt = 0;
|
||||
sym_strt = 0;
|
||||
|
||||
/* Process the interface declaration */
|
||||
|
||||
exportedProcedureHeading();
|
||||
} /* end else if */
|
||||
else break;
|
||||
} /* end for */
|
||||
|
||||
/* We are finished with the interface section */
|
||||
|
||||
FP->section = eIsOtherSection;
|
||||
}
|
||||
|
||||
/* Process Procedure Declaration Block */
|
||||
|
||||
static void exportedProcedureHeading(void)
|
||||
{
|
||||
uint16_t procLabel = ++label;
|
||||
char *saveChSp;
|
||||
STYPE *procPtr;
|
||||
register int i;
|
||||
|
||||
TRACE(lstFile,"[exportedProcedureHeading]");
|
||||
|
||||
/* FORM: procedure-heading =
|
||||
* 'procedure' identifier [ formal-parameter-list ]
|
||||
* FORM: procedure-identifier = identifier
|
||||
*
|
||||
* On entry, token refers to token AFTER the 'procedure' reserved
|
||||
* word.
|
||||
*/
|
||||
|
||||
/* Process the procedure-heading */
|
||||
|
||||
if (token != tIDENT)
|
||||
{
|
||||
error (eIDENT);
|
||||
return;
|
||||
} /* endif */
|
||||
|
||||
procPtr = addProcedure(tkn_strt, sPROC, procLabel, 0, NULL);
|
||||
|
||||
/* Mark the procedure as external */
|
||||
|
||||
procPtr->sParm.p.flags |= SPROC_EXTERNAL;
|
||||
|
||||
/* Save the string stack pointer so that we can release all
|
||||
* formal parameter strings later. Then get the next token.
|
||||
*/
|
||||
|
||||
saveChSp = stringSP;
|
||||
getToken();
|
||||
|
||||
/* NOTE: The level associated with the PROCEDURE symbol is the level
|
||||
* At which the procedure was declared. Everything declare within the
|
||||
* PROCEDURE is at the next level
|
||||
*/
|
||||
|
||||
level++;
|
||||
|
||||
/* Process parameter list */
|
||||
|
||||
(void)formalParameterList(procPtr);
|
||||
|
||||
if (token != ';') error (eSEMICOLON);
|
||||
else getToken();
|
||||
|
||||
/* If we are compiling a program or unit that "imports" the
|
||||
* procedure then generate the appropriate symbol table entries
|
||||
* in the output file to support relocation when the external
|
||||
* procedure is called.
|
||||
*/
|
||||
|
||||
if (includeIndex > 0)
|
||||
{
|
||||
pas_GenerateProcImport(procPtr);
|
||||
}
|
||||
|
||||
/* Destroy formal parameter names */
|
||||
|
||||
for (i = 1; i <= procPtr->sParm.p.nParms; i++)
|
||||
{
|
||||
procPtr[i].sName = NULL;
|
||||
}
|
||||
stringSP = saveChSp;
|
||||
|
||||
/* Drop the level back to where it was */
|
||||
|
||||
level--;
|
||||
|
||||
} /* end exportedProcedureHeading */
|
||||
|
||||
/***************************************************************/
|
||||
/* Process Function Declaration Block */
|
||||
|
||||
static void exportedFunctionHeading(void)
|
||||
{
|
||||
uint16_t funcLabel = ++label;
|
||||
int16_t parameterOffset;
|
||||
char *saveChSp;
|
||||
STYPE *funcPtr;
|
||||
register int i;
|
||||
|
||||
TRACE(lstFile,"[exportedFunctionHeading]");
|
||||
|
||||
/* FORM: function-declaration =
|
||||
* function-heading ';' directive |
|
||||
* function-heading ';' function-block
|
||||
* FORM: function-heading =
|
||||
* 'function' function-identifier [ formal-parameter-list ]
|
||||
* ':' result-type
|
||||
*
|
||||
* On entry token should lrefer to the function-identifier.
|
||||
*/
|
||||
|
||||
/* Verify function-identifier */
|
||||
|
||||
if (token != tIDENT)
|
||||
{
|
||||
error (eIDENT);
|
||||
return;
|
||||
} /* endif */
|
||||
|
||||
funcPtr = addProcedure(tkn_strt, sFUNC, funcLabel, 0, NULL);
|
||||
|
||||
/* Mark the procedure as external */
|
||||
|
||||
funcPtr->sParm.p.flags |= SPROC_EXTERNAL;
|
||||
|
||||
/* NOTE: The level associated with the FUNCTION symbol is the level
|
||||
* At which the procedure was declared. Everything declare within the
|
||||
* PROCEDURE is at the next level
|
||||
*/
|
||||
|
||||
level++;
|
||||
|
||||
/* Save the string stack pointer so that we can release all
|
||||
* formal parameter strings later. Then get the next token.
|
||||
*/
|
||||
|
||||
saveChSp = stringSP;
|
||||
getToken();
|
||||
|
||||
/* Process parameter list */
|
||||
|
||||
parameterOffset = formalParameterList(funcPtr);
|
||||
|
||||
/* Verify that the parameter list is followed by a colon */
|
||||
|
||||
if (token != ':') error (eCOLON);
|
||||
else getToken();
|
||||
|
||||
/* Get function type, return value type/size and offset to return value */
|
||||
|
||||
if (token == sTYPE)
|
||||
{
|
||||
/* The offset to the return value is the offset to the last
|
||||
* parameter minus the size of the return value (aligned to
|
||||
* multiples of size of INTEGER).
|
||||
*/
|
||||
|
||||
parameterOffset -= tknPtr->sParm.t.rsize;
|
||||
parameterOffset = intAlign(parameterOffset);
|
||||
|
||||
/* Save the TYPE for the function */
|
||||
|
||||
funcPtr->sParm.p.parent = tknPtr;
|
||||
|
||||
/* Skip over the result-type token */
|
||||
|
||||
getToken();
|
||||
} /* end if */
|
||||
else
|
||||
{
|
||||
error(eINVTYPE);
|
||||
}
|
||||
|
||||
/* Verify the final semicolon */
|
||||
|
||||
if (token != ';') error (eSEMICOLON);
|
||||
else getToken();
|
||||
|
||||
/* If we are compiling a program or unit that "imports" the
|
||||
* function then generate the appropriate symbol table entries
|
||||
* in the output file to support relocation when the external
|
||||
* function is called.
|
||||
*/
|
||||
|
||||
if (includeIndex > 0)
|
||||
{
|
||||
pas_GenerateProcImport(funcPtr);
|
||||
}
|
||||
|
||||
/* Destroy formal parameter names and the function return value name */
|
||||
|
||||
for (i = 1; i <= funcPtr->sParm.p.nParms; i++)
|
||||
{
|
||||
funcPtr[i].sName = ((char *) NULL);
|
||||
}
|
||||
stringSP = saveChSp;
|
||||
|
||||
/* Restore the original level */
|
||||
|
||||
level--;
|
||||
|
||||
} /* end exportedFunctionHeading */
|
||||
@@ -0,0 +1,51 @@
|
||||
/***************************************************************************
|
||||
* punit.h
|
||||
* External Declarations associated with punit.c
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __PUNIT_H
|
||||
#define __PUNIT_H
|
||||
|
||||
/***************************************************************************
|
||||
* Public Types
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* Global Function Prototypes
|
||||
***************************************************************************/
|
||||
|
||||
extern void unitImplementation(void);
|
||||
extern void unitInterface(void);
|
||||
|
||||
#endif /* __PUNIT_H */
|
||||
Reference in New Issue
Block a user