2022-10-19 20:16:13 +00:00
|
|
|
#include "cmdline.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <util.h>
|
|
|
|
|
|
|
|
extern char STSbuf[256];
|
|
|
|
|
|
|
|
static int ioLineNum;
|
|
|
|
static Boolean printedAnything;
|
|
|
|
static char arrowBuf[256];
|
|
|
|
static Boolean newErr;
|
|
|
|
static Boolean newSrc;
|
|
|
|
static Boolean srcIsErr;
|
|
|
|
static OSSpec errSpec;
|
|
|
|
static OSSpec srcSpec;
|
|
|
|
static Boolean validErr;
|
|
|
|
static Boolean validSrc;
|
|
|
|
static SInt32 lastPrintingPlugin;
|
|
|
|
static Boolean ioInHelp;
|
|
|
|
static Boolean ioPiping;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
|
|
|
static void catchinterrupt() {
|
2022-10-19 20:16:13 +00:00
|
|
|
clState.userBreak = 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
static void SetupConsoleInfo(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
struct winsize ws;
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
signal(SIGINT, catchinterrupt);
|
|
|
|
ioPiping = 0;
|
|
|
|
|
|
|
|
fstat(stdout->_file, &st);
|
|
|
|
if (st.st_mode & 0x1000)
|
|
|
|
ioPiping = 1;
|
|
|
|
fstat(stderr->_file, &st);
|
|
|
|
if (st.st_mode & 0x1000)
|
|
|
|
ioPiping = 1;
|
|
|
|
|
|
|
|
if (ioPiping) {
|
|
|
|
ws.ws_row = 0;
|
|
|
|
ws.ws_col = 80;
|
|
|
|
} else if (ioctl(stdout->_file, TIOCGWINSZ, &ws) < 0) {
|
|
|
|
ioPiping = 1;
|
|
|
|
ws.ws_row = 0;
|
|
|
|
ws.ws_col = 80;
|
|
|
|
}
|
|
|
|
|
|
|
|
optsEnvir.rows = ws.ws_row;
|
|
|
|
optsEnvir.cols = ws.ws_col;
|
|
|
|
if (optsEnvir.cols > 256)
|
|
|
|
optsEnvir.cols = 256;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void Crash() {
|
2022-10-19 20:16:13 +00:00
|
|
|
*((unsigned char *) NULL) = 0;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
void SetupDebuggingTraps(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
signal(SIGABRT, Crash);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
Boolean IO_Initialize(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
ioPiping = 0;
|
|
|
|
ioInHelp = 0;
|
|
|
|
ioLineNum = 0;
|
|
|
|
SetupConsoleInfo();
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
if (ioPiping) {
|
|
|
|
setvbuf(stdout, NULL, 0, 1024);
|
|
|
|
setvbuf(stderr, NULL, 0, 1024);
|
|
|
|
} else {
|
|
|
|
setvbuf(stdout, NULL, 1, 1024);
|
|
|
|
setvbuf(stderr, NULL, 1, 1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
InitWorking();
|
|
|
|
return 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
Boolean IO_Terminate(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (ioInHelp)
|
|
|
|
IO_HelpTerminate();
|
|
|
|
TermWorking();
|
|
|
|
return 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
Boolean IO_HelpInitialize(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
ioInHelp = 1;
|
|
|
|
return 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
Boolean IO_HelpTerminate(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
ioInHelp = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean SendHandleToFile(FILE *file, Handle text, SInt32 size) {
|
|
|
|
Boolean ret;
|
|
|
|
char *ptr;
|
|
|
|
char *lineEnd;
|
|
|
|
char *end;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
if (file != stdout && file != stderr)
|
|
|
|
setvbuf(file, NULL, 0, 1024);
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
HLock(text);
|
|
|
|
ptr = *text;
|
|
|
|
if (size && ptr[size - 1] == 0)
|
|
|
|
size--;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
if (size <= 0) {
|
|
|
|
ret = 1;
|
|
|
|
} else {
|
|
|
|
end = ptr + size;
|
|
|
|
while (ptr < end) {
|
|
|
|
lineEnd = ptr;
|
|
|
|
while (lineEnd < end && *lineEnd != '\n' && *lineEnd != '\r')
|
|
|
|
lineEnd++;
|
|
|
|
|
|
|
|
if (lineEnd - ptr) {
|
|
|
|
if (fwrite(ptr, lineEnd - ptr, 1, file) != 1) {
|
|
|
|
CLReportCError(10, errno);
|
|
|
|
ret = 0;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CheckForUserBreak()) {
|
|
|
|
ret = 1;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
// I have a hunch that this "\n" might be a define
|
|
|
|
if (fwrite("\n", strlen("\n"), 1, file) != 1) {
|
|
|
|
CLReportCError(10, errno);
|
|
|
|
ret = 0;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lineEnd < end && *(lineEnd++) == '\r' && *lineEnd == '\n')
|
|
|
|
++lineEnd;
|
|
|
|
ptr = lineEnd;
|
|
|
|
}
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fail:
|
|
|
|
HUnlock(text);
|
|
|
|
fflush(file);
|
|
|
|
|
|
|
|
if (file != stdout && file != stderr)
|
|
|
|
setvbuf(file, NULL, 2, 1024);
|
|
|
|
|
|
|
|
return ret;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
void FixHandleForIDE(Handle text, UInt32 size) {
|
|
|
|
char *ptr;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
HLock(text);
|
|
|
|
for (ptr = *text; ptr < (*text + size); ptr++) {
|
|
|
|
if (*ptr == '\r')
|
|
|
|
*ptr = '\n';
|
|
|
|
}
|
|
|
|
HUnlock(text);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
Boolean ShowHandle(Handle text, UInt32 size, Boolean decorate) {
|
|
|
|
static const char *border = "===============\n";
|
|
|
|
|
|
|
|
if (decorate)
|
|
|
|
fprintf(stdout, border);
|
|
|
|
if (!SendHandleToFile(stdout, text, size))
|
|
|
|
return 0;
|
|
|
|
if (decorate)
|
|
|
|
fprintf(stdout, border);
|
|
|
|
fflush(stdout);
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
return 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
Boolean WriteHandleToFile(OSSpec *spec, Handle text, UInt32 size, OSType creator, OSType type) {
|
|
|
|
FILE *file;
|
|
|
|
char path[256];
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
OS_SpecToString(spec, path, sizeof(path));
|
|
|
|
file = fopen(path, "w+b");
|
|
|
|
if (!file) {
|
|
|
|
CLReportCError(8, errno, path);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendHandleToFile(file, text, size);
|
|
|
|
fclose(file);
|
|
|
|
|
|
|
|
OS_SetMacFileCreatorAndType(spec, creator, type);
|
|
|
|
return 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Boolean WriteBinaryHandleToFile(OSSpec *spec, CWDataType maccreator, CWDataType mactype, OSHandle *text) {
|
2022-10-19 20:16:13 +00:00
|
|
|
int err;
|
|
|
|
OSFileHandle file;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
if ((err = OS_NewFileHandle(spec, text, 1, &file)) || (err = OS_FreeFileHandle(&file)) || (err = OS_SetMacFileCreatorAndType(spec, maccreator, mactype))) {
|
|
|
|
CLReportOSError(8, err, OS_SpecToString(spec, STSbuf, sizeof(STSbuf)));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
Boolean AppendHandleToFile(OSSpec *spec, Handle text, UInt32 size, CWDataType maccreator, CWDataType mactype) {
|
|
|
|
FILE *file;
|
|
|
|
char path[256];
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
OS_SpecToString(spec, path, sizeof(path));
|
|
|
|
file = fopen(path, "a+b");
|
|
|
|
if (!file) {
|
|
|
|
CLReportCError(8, errno, path);
|
|
|
|
return 0;
|
|
|
|
}
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
SendHandleToFile(file, text, size);
|
|
|
|
fclose(file);
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
OS_SetMacFileCreatorAndType(spec, maccreator, mactype);
|
|
|
|
return 1;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
void InitWorking(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
}
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
void ShowWorking(int x) {
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
void TermWorking(void) {
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ProgressFunction(const char *functionname) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (optsCmdLine.verbose)
|
2023-01-15 21:50:41 +00:00
|
|
|
CLReport(CLStr7, functionname);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:29:53 +00:00
|
|
|
Boolean CheckForUserBreak(void) {
|
2022-10-19 20:16:13 +00:00
|
|
|
ShowWorking(4);
|
|
|
|
return clState.userBreak;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
char *buffer;
|
|
|
|
int pos;
|
|
|
|
int maxlen;
|
|
|
|
SInt16 col;
|
2022-10-19 20:16:13 +00:00
|
|
|
Boolean original;
|
2022-10-11 02:18:42 +00:00
|
|
|
char *newline;
|
|
|
|
} UnkCLIOStruct;
|
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
// unknown names for these inlines
|
2023-01-11 23:26:04 +00:00
|
|
|
CW_INLINE void appendText(UnkCLIOStruct *f, const char *str) {
|
2022-10-19 20:16:13 +00:00
|
|
|
int len = strlen(str);
|
|
|
|
|
|
|
|
if (f->pos + len >= f->maxlen) {
|
|
|
|
f->maxlen = f->maxlen * 2 + len;
|
|
|
|
if (f->original) {
|
|
|
|
char *oldbuf;
|
|
|
|
oldbuf = f->buffer;
|
|
|
|
f->buffer = xmalloc("message buffer", f->maxlen);
|
|
|
|
memcpy(f->buffer, oldbuf, f->pos);
|
|
|
|
} else {
|
|
|
|
f->buffer = xrealloc("message buffer", f->original ? NULL : f->buffer, f->maxlen);
|
|
|
|
}
|
|
|
|
f->original = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(f->buffer + f->pos, str, len);
|
|
|
|
f->pos += len;
|
|
|
|
f->col += len;
|
|
|
|
}
|
2023-01-11 23:26:04 +00:00
|
|
|
CW_INLINE void appendChar(UnkCLIOStruct *f, char c) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (f->pos >= f->maxlen) {
|
|
|
|
f->maxlen *= 2;
|
|
|
|
if (f->original) {
|
|
|
|
char *oldbuf = f->buffer;
|
|
|
|
f->buffer = xmalloc("message buffer", f->maxlen);
|
|
|
|
memcpy(f->buffer, oldbuf, f->pos);
|
|
|
|
} else {
|
|
|
|
f->buffer = xrealloc("message buffer", f->buffer, f->maxlen);
|
|
|
|
}
|
|
|
|
f->original = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
f->buffer[f->pos++] = c;
|
|
|
|
f->col++;
|
|
|
|
}
|
|
|
|
|
2022-10-11 02:18:42 +00:00
|
|
|
static void StartLine(UnkCLIOStruct *f) {
|
2022-10-19 20:16:13 +00:00
|
|
|
f->col = 0;
|
|
|
|
if (!optsEnvir.underIDE && f->newline)
|
|
|
|
appendText(f, f->newline);
|
|
|
|
}
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2023-01-11 23:26:04 +00:00
|
|
|
CW_INLINE void newLine(UnkCLIOStruct *f) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (f->newline)
|
|
|
|
appendChar(f, '\n');
|
|
|
|
else
|
|
|
|
appendChar(f, ' ');
|
|
|
|
StartLine(f);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void WrapText(UnkCLIOStruct *f) {
|
2022-10-19 20:16:13 +00:00
|
|
|
int wrapped;
|
|
|
|
char wrapbuf[256];
|
|
|
|
char c;
|
|
|
|
|
|
|
|
wrapped = 0;
|
|
|
|
if (optsCmdLine.noWrapOutput)
|
|
|
|
return;
|
|
|
|
if (!f->newline)
|
|
|
|
return;
|
|
|
|
if (strlen(f->newline) > optsEnvir.cols / 2)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (wrapped < (optsEnvir.cols - 1) && f->col > strlen(f->newline)) {
|
|
|
|
c = f->buffer[f->pos - 1];
|
|
|
|
if (c == ' ') break;
|
|
|
|
if (c == '/') break;
|
|
|
|
if (c == '-') break;
|
|
|
|
wrapbuf[wrapped] = c;
|
|
|
|
f->pos = f->pos - 1;
|
|
|
|
f->col = f->col - 1;
|
|
|
|
wrapped++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f->col <= strlen(f->newline)) {
|
|
|
|
while (f->col < (optsEnvir.cols - 1) && wrapped > 0) {
|
|
|
|
appendChar(f, wrapbuf[--wrapped]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
newLine(f);
|
|
|
|
while (wrapped > 0 && f->maxlen > 0) {
|
|
|
|
appendChar(f, wrapbuf[--wrapped]);
|
|
|
|
}
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *IO_VFormatText(char *buffer, SInt32 size, char *newline, const char *format, va_list ap) {
|
2022-10-19 20:16:13 +00:00
|
|
|
UnkCLIOStruct f;
|
|
|
|
char *arg;
|
|
|
|
|
|
|
|
f.buffer = buffer;
|
|
|
|
f.pos = 0;
|
|
|
|
f.maxlen = size;
|
|
|
|
f.col = 0;
|
|
|
|
f.original = 1;
|
|
|
|
f.newline = newline;
|
|
|
|
StartLine(&f);
|
|
|
|
|
|
|
|
while (*format && f.maxlen > 0) {
|
|
|
|
if (*format == '%') {
|
|
|
|
arg = va_arg(ap, char *);
|
|
|
|
while (*arg && f.maxlen > 0) {
|
|
|
|
if (*arg == '\r' || *arg == '\n') {
|
|
|
|
newLine(&f);
|
|
|
|
arg++;
|
|
|
|
} else if (*arg == '\t') {
|
|
|
|
if (f.maxlen > 0) {
|
|
|
|
do {
|
|
|
|
appendChar(&f, ' ');
|
|
|
|
} while (f.col & 7);
|
|
|
|
}
|
|
|
|
arg++;
|
|
|
|
} else {
|
|
|
|
appendChar(&f, *(arg++));
|
|
|
|
if (!optsCmdLine.noWrapOutput && f.newline && f.col >= optsEnvir.cols - 1)
|
|
|
|
WrapText(&f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
format++;
|
|
|
|
} else if (*format == '\r' || *format == '\n') {
|
|
|
|
format++;
|
|
|
|
newLine(&f);
|
|
|
|
} else {
|
|
|
|
appendChar(&f, *(format++));
|
|
|
|
if (!optsCmdLine.noWrapOutput && f.col >= optsEnvir.cols - 1)
|
|
|
|
WrapText(&f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f.newline) {
|
|
|
|
if (f.col == strlen(f.newline)) {
|
|
|
|
f.pos -= f.col;
|
|
|
|
f.col = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
appendChar(&f, 0);
|
|
|
|
|
|
|
|
return f.buffer;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *IO_FormatText(char *buffer, SInt32 size, char *newline, const char *format, ...) {
|
2022-10-19 20:16:13 +00:00
|
|
|
va_list ap;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
ret = IO_VFormatText(buffer, size, newline, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO unify me with the one in the header
|
|
|
|
enum {
|
|
|
|
Msg_Note = 1,
|
|
|
|
Msg_Warning = 2,
|
|
|
|
Msg_Error = 3,
|
|
|
|
Msg_Alert = 4,
|
|
|
|
Msg_Status = 5
|
|
|
|
};
|
|
|
|
void CLPrintDispatch(int unk, SInt16 msgtype, const char *message) {
|
|
|
|
FILE *out;
|
|
|
|
const char *ptr;
|
|
|
|
const char *nptr;
|
|
|
|
|
2023-01-11 23:26:04 +00:00
|
|
|
if (optsCmdLine.stderr2stdout == 1 || msgtype == Msg_Note || msgtype == Msg_Status)
|
2022-10-19 20:16:13 +00:00
|
|
|
out = stdout;
|
2023-01-11 23:26:04 +00:00
|
|
|
else if (msgtype == Msg_Warning || msgtype == Msg_Error || msgtype == Msg_Alert)
|
2022-10-19 20:16:13 +00:00
|
|
|
out = stderr;
|
2023-01-11 23:26:04 +00:00
|
|
|
else
|
|
|
|
OS_ASSERT(847, 0);
|
2022-10-19 20:16:13 +00:00
|
|
|
|
|
|
|
if (!printedAnything && !ioPiping) {
|
|
|
|
printedAnything = 1;
|
|
|
|
ioLineNum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = message;
|
|
|
|
while (*ptr) {
|
|
|
|
nptr = ptr;
|
|
|
|
while (*nptr && *nptr != '\n' && *nptr != '\r')
|
|
|
|
++nptr;
|
|
|
|
|
|
|
|
if (nptr - ptr) {
|
|
|
|
if (fwrite(ptr, nptr - ptr, 1, out) != 1)
|
|
|
|
clState.userBreak = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*nptr) {
|
|
|
|
ioLineNum++;
|
|
|
|
fwrite("\n", strlen("\n"), 1, out);
|
|
|
|
if (*nptr == '\r')
|
|
|
|
nptr++;
|
|
|
|
if (*nptr == '\n')
|
|
|
|
nptr++;
|
|
|
|
if (nptr[0] && !nptr[1] && (nptr[0] == '\n' || nptr[0] == '\r'))
|
|
|
|
nptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = nptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (out == stdout && optsCmdLine.verbose > 1)
|
|
|
|
fflush(out);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void GetFileInfo(MessageRef *ref) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (ref) {
|
|
|
|
srcIsErr = OS_EqualSpec(&ref->sourcefile, &ref->errorfile);
|
|
|
|
if (!validSrc || !OS_EqualSpec(&ref->sourcefile, &srcSpec)) {
|
|
|
|
newSrc = 1;
|
|
|
|
srcSpec = ref->sourcefile;
|
|
|
|
validSrc = 1;
|
|
|
|
} else {
|
|
|
|
newSrc = 0;
|
|
|
|
}
|
|
|
|
if (!validErr || !OS_EqualSpec(&ref->errorfile, &errSpec)) {
|
|
|
|
newErr = 1;
|
|
|
|
errSpec = ref->errorfile;
|
|
|
|
validErr = 1;
|
|
|
|
} else {
|
|
|
|
newErr = 0;
|
|
|
|
}
|
|
|
|
}
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *Arrows(MessageRef *ref) {
|
2022-10-19 20:16:13 +00:00
|
|
|
int start;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
arrowBuf[0] = 0;
|
|
|
|
start = ref->tokenoffset;
|
|
|
|
start %= optsEnvir.cols;
|
|
|
|
if (start >= 0 && start < sizeof(arrowBuf)) {
|
|
|
|
len = ref->tokenlength;
|
|
|
|
if (len + start > sizeof(arrowBuf))
|
|
|
|
len = sizeof(arrowBuf) - start;
|
|
|
|
if (len == 0)
|
|
|
|
len = 1;
|
|
|
|
memset(arrowBuf, ' ', start);
|
|
|
|
memset(arrowBuf + start, '^', len);
|
|
|
|
arrowBuf[start + len] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return arrowBuf;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Boolean IsLikelyAnImporter(Plugin *plugin) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (Plugin_CL_GetObjectFlags(plugin)->flags & 0x80000000)
|
|
|
|
return 0;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
return plugin != Plugins_CL_MatchTarget(NULL, gTarg->cpu, gTarg->os, clState.plugintype, clState.language);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *GuessTool(Plugin *plugin) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (plugin) {
|
|
|
|
DropInFlags *df = Plugin_GetDropInFlags(plugin);
|
|
|
|
switch (df->dropintype) {
|
|
|
|
case CWDROPINDRIVERTYPE: return "Driver";
|
|
|
|
case CWDROPINPARSERTYPE: return "Usage";
|
|
|
|
case CWDROPINCOMPILERTYPE:
|
|
|
|
if (df->edit_language == Lang_C_CPP || df->edit_language == Lang_Pascal)
|
|
|
|
return "Compiler";
|
|
|
|
else if (df->edit_language == CWFOURCHAR('A','s','m',' '))
|
|
|
|
return "Assembler";
|
|
|
|
else if (IsLikelyAnImporter(plugin))
|
|
|
|
return "Importer";
|
|
|
|
else
|
|
|
|
return "Compiler";
|
|
|
|
case CWDROPINLINKERTYPE:
|
|
|
|
return "Linker";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "Driver";
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *GuessDoing(Plugin *plugin) {
|
2022-10-19 20:16:13 +00:00
|
|
|
if (plugin) {
|
|
|
|
DropInFlags *df = Plugin_GetDropInFlags(plugin);
|
|
|
|
switch (df->dropintype) {
|
|
|
|
case CWDROPINPARSERTYPE: return "parsing";
|
|
|
|
case CWDROPINCOMPILERTYPE: return "compiling";
|
|
|
|
case CWDROPINLINKERTYPE: return "linking";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "processing";
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *msgnames[6] = {
|
|
|
|
"",
|
|
|
|
"Note",
|
|
|
|
"Warning",
|
|
|
|
"Error",
|
|
|
|
"Alert",
|
|
|
|
"Status"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *msgnames_gcc[6] = {
|
|
|
|
"",
|
|
|
|
" note",
|
|
|
|
" warning",
|
|
|
|
"",
|
|
|
|
" alert",
|
|
|
|
" status"
|
|
|
|
};
|
|
|
|
|
|
|
|
static void styledMessage_MPW(Plugin *plugin, MessageRef *ref, SInt32 errorNumber, SInt16 msgType, const char *format, va_list va) {
|
|
|
|
char msgBuf[256];
|
|
|
|
char *msgPtr;
|
|
|
|
|
|
|
|
msgPtr = IO_VFormatText(msgBuf, sizeof(msgBuf), "# ", format, va);
|
|
|
|
if (msgType != Msg_Status)
|
|
|
|
CLPrintType(msgType, "### %s %s %s:\n", clState.programName, GuessTool(plugin), msgnames[msgType]);
|
|
|
|
|
|
|
|
if (ref) {
|
|
|
|
CLPrintType(msgType, "#\t%s\n", ref->sourceline);
|
|
|
|
CLPrintType(msgType, "#\t%s\n", Arrows(ref));
|
|
|
|
}
|
|
|
|
|
|
|
|
CLPrintDispatch(0, msgType, msgPtr);
|
|
|
|
|
|
|
|
if (ref) {
|
|
|
|
CLPrintType(msgType, "#----------------------------------------------------------\n");
|
|
|
|
CLPrintType(msgType, " File \"%s\"; Line %d\n", OS_SpecToString(&ref->errorfile, STSbuf, sizeof(STSbuf)), ref->linenumber);
|
|
|
|
GetFileInfo(ref);
|
|
|
|
if (!srcIsErr)
|
|
|
|
CLPrintType(msgType, "#\twhile %s \"%s\"\n", GuessDoing(plugin), OS_SpecToString(&ref->sourcefile, STSbuf, sizeof(STSbuf)));
|
|
|
|
CLPrintType(msgType, "#----------------------------------------------------------\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgPtr != msgBuf)
|
|
|
|
free(msgPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void styledMessage_Default(Plugin *plugin, MessageRef *ref, SInt32 errorNumber, SInt16 msgType, const char *format, va_list va) {
|
|
|
|
char lineBuf[320];
|
|
|
|
char msgBuf[256];
|
|
|
|
char *msgPtr;
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
msgPtr = IO_VFormatText(msgBuf, sizeof(msgBuf), "# ", format, va);
|
|
|
|
if (ref) {
|
|
|
|
CLPrintType(msgType, "### %s %s:\n", clState.programName, GuessTool(plugin));
|
|
|
|
} else if (msgType != Msg_Status) {
|
|
|
|
CLPrintType(msgType, "### %s %s %s:\n", clState.programName, GuessTool(plugin), msgnames[msgType]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ref) {
|
|
|
|
GetFileInfo(ref);
|
|
|
|
if (newErr || (newSrc && srcIsErr)) {
|
|
|
|
if (srcIsErr) {
|
|
|
|
sprintf(lineBuf, "#%8s: %s\n", "File", OS_SpecToStringRelative(&errSpec, NULL, STSbuf, sizeof(STSbuf)));
|
|
|
|
} else {
|
|
|
|
sprintf(lineBuf, "#%8s: %s\n", "In", OS_SpecToStringRelative(&errSpec, NULL, STSbuf, sizeof(STSbuf)));
|
|
|
|
}
|
|
|
|
CLPrintDispatch(0, msgType, lineBuf);
|
|
|
|
}
|
|
|
|
if (newSrc && !srcIsErr) {
|
|
|
|
sprintf(lineBuf, "# %7s: %s\n", "From", OS_SpecToStringRelative(&srcSpec, NULL, STSbuf, sizeof(STSbuf)));
|
|
|
|
CLPrintDispatch(0, msgType, lineBuf);
|
|
|
|
}
|
|
|
|
if (newErr || newSrc) {
|
|
|
|
ptr = &lineBuf[2];
|
|
|
|
while (*ptr && *ptr != '\n')
|
|
|
|
*(ptr++) = '-';
|
|
|
|
*ptr = 0;
|
|
|
|
if (ptr - lineBuf >= optsEnvir.cols - 1)
|
|
|
|
lineBuf[optsEnvir.cols - 1] = 0;
|
|
|
|
strcat(lineBuf, "\n");
|
|
|
|
CLPrintDispatch(0, msgType, lineBuf);
|
|
|
|
}
|
|
|
|
CLPrintType(msgType, "#%8d: %s\n", ref->linenumber, ref->sourceline);
|
|
|
|
CLPrintType(msgType, "#%8s: %s\n", msgnames[msgType], Arrows(ref));
|
|
|
|
}
|
|
|
|
|
|
|
|
CLPrintDispatch(0, msgType, msgPtr);
|
|
|
|
if (msgPtr != msgBuf)
|
|
|
|
free(msgPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void styledMessage_Terse(Plugin *plugin, MessageRef *ref, SInt32 errorNumber, SInt16 msgType, const char *format, va_list va) {
|
|
|
|
char *msg;
|
|
|
|
char *ptr;
|
|
|
|
char msgBuf[256];
|
|
|
|
char *msgPtr;
|
|
|
|
char header[256];
|
|
|
|
char *headPtr;
|
|
|
|
char errBuf[256];
|
|
|
|
char *errPtr;
|
|
|
|
|
|
|
|
if (ref) {
|
|
|
|
if (msgnames_gcc[msgType][0]) {
|
|
|
|
headPtr = mprintf(
|
|
|
|
header, sizeof(header),
|
|
|
|
"%s:%d:%s: ",
|
|
|
|
OS_SpecToStringRelative(&ref->errorfile, NULL, STSbuf, sizeof(STSbuf)),
|
|
|
|
ref->linenumber,
|
|
|
|
msgnames_gcc[msgType]
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
headPtr = mprintf(
|
|
|
|
header, sizeof(header),
|
|
|
|
"%s:%d: ",
|
|
|
|
OS_SpecToStringRelative(&ref->errorfile, NULL, STSbuf, sizeof(STSbuf)),
|
|
|
|
ref->linenumber
|
|
|
|
);
|
|
|
|
}
|
|
|
|
} else if (msgType != Msg_Status) {
|
|
|
|
headPtr = mprintf(header, sizeof(header), "%s: ", clState.programName);
|
|
|
|
} else {
|
|
|
|
header[0] = 0;
|
|
|
|
headPtr = header;
|
|
|
|
}
|
|
|
|
|
|
|
|
msgPtr = IO_VFormatText(msgBuf, sizeof(msgBuf), headPtr, format, va);
|
|
|
|
if ((strstr(msgPtr, "#warning") || strstr(msgPtr, "#error")) && ref->sourceline[0]) {
|
|
|
|
errPtr = IO_FormatText(errBuf, sizeof(errBuf), headPtr, "%", ref->sourceline);
|
|
|
|
} else {
|
|
|
|
errPtr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (headPtr != header)
|
|
|
|
free(headPtr);
|
|
|
|
|
|
|
|
msg = msgPtr;
|
|
|
|
while (*msg) {
|
|
|
|
ptr = msg;
|
|
|
|
while (*ptr && *ptr != '\n')
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
CLPrintType(msgType, "%.*s\n", ptr - msg, msg);
|
|
|
|
if (errPtr) {
|
|
|
|
CLPrintType(msgType, "%s\n", errPtr);
|
|
|
|
if (errPtr != errBuf)
|
|
|
|
free(errPtr);
|
|
|
|
errPtr = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ptr)
|
|
|
|
msg = ptr + 1;
|
|
|
|
else
|
|
|
|
msg = ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgPtr != msgBuf)
|
|
|
|
free(msgPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void styledMessage_IDE(Plugin *plugin, MessageRef *ref, SInt32 errorNumber, SInt16 msgType, const char *format, va_list va) {
|
|
|
|
char msgBuf[256];
|
|
|
|
char *msgPtr;
|
|
|
|
SInt16 oldCols;
|
|
|
|
|
|
|
|
oldCols = optsEnvir.cols;
|
|
|
|
msgPtr = IO_VFormatText(msgBuf, sizeof(msgBuf), " ", format, va);
|
|
|
|
optsEnvir.cols = oldCols;
|
|
|
|
|
|
|
|
CLPrintType(msgType, "%8s : %s\n", msgnames[msgType], msgPtr + 11);
|
|
|
|
if (msgPtr != msgBuf)
|
|
|
|
free(msgPtr);
|
|
|
|
|
|
|
|
if (ref) {
|
|
|
|
msgPtr = IO_FormatText(msgBuf, sizeof(msgBuf), "\t", "%", ref->sourceline);
|
|
|
|
CLPrintType(msgType, "%s line %d%s\n", OS_SpecToStringRelative(&ref->errorfile, NULL, STSbuf, sizeof(STSbuf)), ref->linenumber, msgPtr);
|
|
|
|
if (msgPtr != msgBuf)
|
|
|
|
free(msgPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void styledMessage_Parseable(Plugin *plugin, MessageRef *ref, SInt32 errorNumber, SInt16 msgType, const char *format, va_list va) {
|
|
|
|
char msgBuf[256];
|
|
|
|
char *msgPtr;
|
|
|
|
|
|
|
|
CLPrintType(msgType, "%s|%s|%s\n", clState.programName, GuessTool(plugin), msgnames[msgType]);
|
|
|
|
if (ref) {
|
|
|
|
CLPrintType(
|
|
|
|
msgType,
|
|
|
|
"(%s|%d|%d|%d|%d|%d)\n",
|
|
|
|
OS_SpecToString(&ref->errorfile, STSbuf, sizeof(STSbuf)),
|
|
|
|
ref->linenumber,
|
|
|
|
ref->tokenoffset,
|
|
|
|
ref->tokenlength,
|
|
|
|
ref->selectionoffset,
|
|
|
|
ref->selectionlength
|
|
|
|
);
|
|
|
|
CLPrintType(msgType, "=%s\n", ref->sourceline);
|
|
|
|
}
|
|
|
|
|
|
|
|
msgPtr = IO_VFormatText(msgBuf, sizeof(msgBuf), ">", format, va);
|
|
|
|
CLPrintType(msgType, "%s\n", msgPtr);
|
|
|
|
if (msgPtr != msgBuf)
|
|
|
|
free(msgPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CLPrintType(SInt16 msgtype, const char *format, ...) {
|
|
|
|
char printbuffer[256];
|
|
|
|
char *ptr;
|
|
|
|
va_list va;
|
|
|
|
|
|
|
|
va_start(va, format);
|
|
|
|
ptr = mvprintf(printbuffer, sizeof(printbuffer), format, va);
|
|
|
|
va_end(va);
|
|
|
|
CLPrintDispatch(0, msgtype, ptr);
|
|
|
|
if (ptr != printbuffer)
|
|
|
|
free(ptr);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-10-13 16:56:43 +00:00
|
|
|
void CLPrint(const char *format, ...) {
|
2022-10-19 20:16:13 +00:00
|
|
|
char printbuffer[256];
|
|
|
|
char *ptr;
|
|
|
|
va_list va;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
va_start(va, format);
|
|
|
|
ptr = mvprintf(printbuffer, sizeof(printbuffer), format, va);
|
|
|
|
va_end(va);
|
|
|
|
CLPrintDispatch(0, Msg_Note, ptr);
|
|
|
|
if (ptr != printbuffer)
|
|
|
|
free(ptr);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-10-13 16:56:43 +00:00
|
|
|
void CLPrintWarning(const char *format, ...) {
|
2022-10-19 20:16:13 +00:00
|
|
|
char printbuffer[256];
|
|
|
|
char *ptr;
|
|
|
|
va_list va;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
va_start(va, format);
|
|
|
|
ptr = mvprintf(printbuffer, sizeof(printbuffer), format, va);
|
|
|
|
va_end(va);
|
|
|
|
CLPrintDispatch(0, Msg_Warning, ptr);
|
|
|
|
if (ptr != printbuffer)
|
|
|
|
free(ptr);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
2022-10-13 16:56:43 +00:00
|
|
|
void CLPrintErr(const char *format, ...) {
|
2022-10-19 20:16:13 +00:00
|
|
|
char printbuffer[256];
|
|
|
|
char *ptr;
|
|
|
|
va_list va;
|
2022-10-11 02:18:42 +00:00
|
|
|
|
2022-10-19 20:16:13 +00:00
|
|
|
va_start(va, format);
|
|
|
|
ptr = mvprintf(printbuffer, sizeof(printbuffer), format, va);
|
|
|
|
va_end(va);
|
|
|
|
CLPrintDispatch(0, Msg_Error, ptr);
|
|
|
|
if (ptr != printbuffer)
|
|
|
|
free(ptr);
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void FixupMessageRef(MessageRef *ref) {
|
2022-10-19 20:16:13 +00:00
|
|
|
char *bol;
|
|
|
|
char *eol;
|
|
|
|
int len;
|
|
|
|
int scan;
|
|
|
|
|
|
|
|
if (ref->sourceline && *ref->sourceline) {
|
|
|
|
bol = ref->sourceline + ref->tokenoffset;
|
|
|
|
eol = ref->sourceline + ref->tokenoffset + ref->tokenlength - 1;
|
|
|
|
if (eol < bol)
|
|
|
|
eol = bol;
|
|
|
|
while (bol > ref->sourceline && bol[-1] != '\r')
|
|
|
|
bol--;
|
|
|
|
while (*eol && *eol != '\r' && *eol != '\n')
|
|
|
|
eol++;
|
|
|
|
|
|
|
|
len = eol - bol;
|
|
|
|
ref->sourceline = xmalloc("text buffer", len + 1);
|
|
|
|
strncpy(ref->sourceline, bol, len);
|
|
|
|
ref->sourceline[len] = 0;
|
|
|
|
|
|
|
|
for (scan = 0; scan < len; scan++) {
|
|
|
|
if (ref->sourceline[scan] < ' ' || ref->sourceline[scan] >= 127)
|
|
|
|
ref->sourceline[scan] = ' ';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ref->sourceline = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SInt16 CLStyledMessageDispatch(Plugin *plugin, MessageRef *ref, SInt32 errorNumber, SInt16 msgType, const char *format, ...) {
|
|
|
|
va_list va;
|
|
|
|
MessageRef myref;
|
|
|
|
UInt32 ptype;
|
|
|
|
|
|
|
|
if (msgType == Msg_Warning) {
|
|
|
|
ptype = plugin ? Plugin_GetPluginType(plugin) : CWDROPINDRIVERTYPE;
|
|
|
|
if (optsCmdLine.noWarnings)
|
|
|
|
return 0;
|
|
|
|
if ((ptype == CWDROPINDRIVERTYPE || ptype == CWDROPINPARSERTYPE) && optsCmdLine.noCmdLineWarnings)
|
|
|
|
return 0;
|
|
|
|
if (optsCmdLine.warningsAreErrors)
|
|
|
|
msgType = Msg_Error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType == Msg_Error && clState.withholdErrors)
|
|
|
|
return 0;
|
|
|
|
if (msgType == Msg_Warning && clState.withholdWarnings)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ref) {
|
|
|
|
myref = *ref;
|
|
|
|
FixupMessageRef(&myref);
|
|
|
|
}
|
|
|
|
|
|
|
|
va_start(va, format);
|
|
|
|
if (optsCmdLine.msgStyle == 2) {
|
|
|
|
styledMessage_MPW(plugin, ref ? &myref : 0, errorNumber, msgType, format, va);
|
|
|
|
} else if (optsCmdLine.msgStyle == 1) {
|
|
|
|
styledMessage_Terse(plugin, ref ? &myref : 0, errorNumber, msgType, format, va);
|
|
|
|
} else if (optsCmdLine.msgStyle == 3) {
|
|
|
|
styledMessage_IDE(plugin, ref ? &myref : 0, errorNumber, msgType, format, va);
|
|
|
|
} else if (optsCmdLine.msgStyle == 4) {
|
|
|
|
styledMessage_Parseable(plugin, ref ? &myref : 0, errorNumber, msgType, format, va);
|
|
|
|
} else {
|
|
|
|
styledMessage_Default(plugin, ref ? &myref : 0, errorNumber, msgType, format, va);
|
|
|
|
}
|
|
|
|
va_end(va);
|
|
|
|
|
|
|
|
if (ref && myref.sourceline)
|
|
|
|
xfree(myref.sourceline);
|
|
|
|
|
|
|
|
if (msgType == Msg_Error && optsCmdLine.maxErrors) {
|
|
|
|
if (++clState.countErrors >= optsCmdLine.maxErrors) {
|
|
|
|
clState.withholdErrors = 1;
|
|
|
|
if (!optsCompiler.noFail) {
|
2023-01-15 21:50:41 +00:00
|
|
|
CLReport(CLStr70);
|
2022-10-19 20:16:13 +00:00
|
|
|
clState.userBreak = 1;
|
|
|
|
} else {
|
2023-01-15 21:50:41 +00:00
|
|
|
CLReport(CLStr71);
|
2022-10-19 20:16:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msgType == Msg_Warning && optsCmdLine.maxWarnings) {
|
|
|
|
if (++clState.countWarnings >= optsCmdLine.maxWarnings) {
|
|
|
|
clState.withholdWarnings = 1;
|
2023-01-15 21:50:41 +00:00
|
|
|
CLReport(CLStr72);
|
2022-10-19 20:16:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return msgType;
|
2022-10-11 02:18:42 +00:00
|
|
|
}
|