ack/lang/cem/cemcom.ansi/l_comment.c
1994-06-27 08:03:14 +00:00

212 lines
3.9 KiB
C

/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Id$ */
/* Lint-specific comment handling */
#include <ctype.h>
#include "lint.h"
#ifdef LINT
#include <alloc.h>
#include "interface.h"
#include "arith.h"
#include "l_state.h"
#include "l_comment.h"
extern char loptions[];
/* Since the lexical analyser does a one-token look-ahead, pseudo-
comments are read too soon. This is remedied by first storing them
in static variables and then moving them to the real variables
one token later.
*/
PRIVATE int notreached;
PRIVATE int varargsN = -1;
PRIVATE int argsused;
PRIVATE int formatN;
PRIVATE int formatVAR;
PRIVATE char *format;
PRIVATE char *prev_format;
PRIVATE make_format();
int LINTLIB; /* file is lint library */
int s_NOTREACHED; /* statement not reached */
int f_VARARGSn; /* function with variable # of args */
int f_ARGSUSED; /* function does not use all args */
int f_FORMATn; /* argument f_FORMATn is f_FORMAT */
char *f_FORMAT;
int f_FORMATvar; /* but the formal argument may be
absent because of varargs.h */
lint_init_comment()
{
LINTLIB = loptions['L'];
}
lint_comment_ahead()
{
s_NOTREACHED = notreached;
notreached = 0;
}
lint_comment_function()
{
f_ARGSUSED = argsused | loptions['v'];
argsused = 0;
f_VARARGSn = varargsN;
varargsN = -1;
f_FORMATn = formatN;
formatN = 0;
f_FORMAT = format;
if (format)
prev_format = format;
format = 0;
f_FORMATvar = formatVAR;
formatVAR = 0;
}
PRIVATE char buf[1000];
PRIVATE char *bufpos; /* next free position in buf */
lint_start_comment()
{
bufpos = &buf[0];
}
lint_comment_char(c)
int c;
{
/* This function is called with every character between /_* and *_/ */
if (bufpos - &buf[0] < sizeof(buf)-1)
*bufpos++ = (char)c;
}
lint_end_comment()
{
*bufpos++ = '\0';
bufpos = &buf[0];
/* skip initial blanks */
while (*bufpos && isspace(*bufpos)) {
bufpos++;
}
/* now test for one of the pseudo-comments */
if (strncmp(bufpos, "NOTREACHED", 10) == 0) {
notreached = 1;
}
else
if (strncmp(bufpos, "ARGSUSED", 8) == 0) {
argsused = 1;
}
else
if (strncmp(bufpos, "LINTLIBRARY", 11) == 0) {
LINTLIB = 1;
}
else
if (strncmp(bufpos, "VARARGS", 7) == 0) {
bufpos += 7;
varargsN = isdigit(*bufpos) ? atoi(bufpos) : 0;
}
else
if (strncmp(bufpos, "FORMAT", 6) == 0 && isdigit(bufpos[6])) {
register int argn;
bufpos += 6;
argn = *bufpos++ - '0';
varargsN = argn + 1;
if (*bufpos == 'v') {
/* something like FORMAT3v */
formatVAR = 1;
bufpos++;
}
make_format(argn, bufpos);
}
}
/* We use a small FSA to skip layout inside formats, but to preserve
a space between letters and digits.
*/
#define NONE 0
#define LETGIT 1
#define LETGITSPACE 2
PRIVATE
make_format(argn, oldf)
int argn;
char *oldf;
{
register char *newf;
register int last_stat;
while (*oldf && *oldf != '$') {
oldf++;
}
if (!*oldf) {
/* no format given, repeat previous format */
if (!prev_format) {
warning("format missing and no previous format");
}
formatN = argn;
format = prev_format;
return;
}
if (*oldf++ != '$') {
warning("no format in FORMAT pseudo-comment");
format = 0;
return;
}
/* there is a new format to be composed */
newf = Malloc(strlen(oldf));
/* certainly enough and probably not overly too much */
formatN = argn;
format = newf;
last_stat = NONE;
while (*oldf && *oldf != '$') {
register char ch = *oldf++;
if (isspace(ch)) {
if (last_stat == LETGIT)
last_stat = LETGITSPACE;
}
else
if (isalnum(ch)) {
switch (last_stat) {
case NONE:
last_stat = LETGIT;
break;
case LETGITSPACE:
*newf++ = ' ';
last_stat = LETGIT;
break;
}
*newf++ = ch;
}
else {
last_stat = NONE;
*newf++ = ch;
}
}
if (*oldf != '$') {
warning("no end of format in FORMAT pseudo-comment");
format = 0;
return;
}
*newf++ = '\0';
}
#endif /* LINT */