From d1f153d34b023d81768f6087f67dbfff714bafc9 Mon Sep 17 00:00:00 2001
From: Ash Wolf <ninji@wuffs.org>
Date: Wed, 19 Oct 2022 21:16:13 +0100
Subject: let's commit all this before my VM blows up and nukes my work

---
 command_line/CmdLine/Src/Envir/CLErrors.c |  91 +++-
 command_line/CmdLine/Src/Envir/CLIO.c     | 852 +++++++++++++++++++++++++++---
 2 files changed, 876 insertions(+), 67 deletions(-)

(limited to 'command_line/CmdLine/Src/Envir')

diff --git a/command_line/CmdLine/Src/Envir/CLErrors.c b/command_line/CmdLine/Src/Envir/CLErrors.c
index 76ff06f..591e30d 100644
--- a/command_line/CmdLine/Src/Envir/CLErrors.c
+++ b/command_line/CmdLine/Src/Envir/CLErrors.c
@@ -1,37 +1,114 @@
-#include "mwcc_decomp.h"
-
-static void CLGetErrorString(SInt16 errid, char *buffer) {
+#include "cmdline.h"
 
+static char *CLGetErrorString(SInt16 errid, char *buffer) {
+    getindstring(buffer, 12000, errid);
+    strcat(buffer, "\n");
+    return buffer;
 }
 
 static void CLMessageReporter(int flags, SInt16 errid, va_list va) {
-
+    static char stmsg[256];
+    static char stbuf[256];
+    char *ptr;
+
+    CLGetErrorString(errid, stmsg);
+    ptr = mvprintf(stbuf, sizeof(stbuf), stmsg, va);
+
+    CLStyledMessageDispatch(
+            NULL,
+            NULL,
+            0,
+            (flags == messagetypeError) ? CLStyledMessageDispatch_Type3 : (flags == messagetypeWarning) ? CLStyledMessageDispatch_Type2 : CLStyledMessageDispatch_Type5,
+            "%",
+            ptr);
+
+    if (ptr != stbuf)
+        free(ptr);
 }
 
 void CLReportError(SInt16 errid, ...) {
-
+    va_list va;
+    va_start(va, errid);
+    CLMessageReporter(messagetypeError, errid, va);
+    va_end(va);
 }
 
 void CLReportWarning(SInt16 errid, ...) {
-
+    va_list va;
+    va_start(va, errid);
+    CLMessageReporter(messagetypeWarning, errid, va);
+    va_end(va);
 }
 
 void CLReport(SInt16 errid, ...) {
-
+    va_list va;
+    va_start(va, errid);
+    CLMessageReporter(messagetypeInfo, errid, va);
+    va_end(va);
 }
 
 void CLReportOSError(SInt16 errid, int err, ...) {
+    char *txt;
+    const char *oserr;
+    char mybuf[256];
+    char myerr[256];
+    va_list va;
+
+    va_start(va, err);
+    txt = mvprintf(mybuf, sizeof(mybuf), CLGetErrorString(errid, myerr), va);
+    va_end(va);
 
+    oserr = OS_GetErrText(err);
+    CLReportError(99, txt, oserr, err);
+
+    if (txt != mybuf)
+        free(txt);
 }
 
 void CLReportCError(SInt16 errid, int err_no, ...) {
+    char *txt;
+    const char *serr;
+    char mybuf[256];
+    char myerr[256];
+    va_list va;
+
+    va_start(va, err_no);
+    txt = mvprintf(mybuf, sizeof(mybuf), CLGetErrorString(errid, myerr), va);
+    va_end(va);
+
+    serr = strerror(err_no);
+    CLReportError(100, txt, serr, err_no);
 
+    if (txt != mybuf)
+        free(txt);
 }
 
 void CLInternalError(const char *file, int line, const char *format, ...) {
+    char mybuf[256];
+    char *txt;
+    va_list va;
 
+    va_start(va, format);
+    txt = mvprintf(mybuf, sizeof(mybuf), format, va);
+    va_end(va);
+    CLPrintErr("INTERNAL ERROR [%s:%d]:\n%s\n", file, line, txt);
+
+    if (txt != mybuf)
+        free(txt);
 }
 
 void CLFatalError(const char *format, ...) {
+    char mybuf[256];
+    char *txt;
+    va_list va;
+
+    va_start(va, format);
+    txt = mvprintf(mybuf, sizeof(mybuf), format, va);
+    va_end(va);
+    CLPrintErr("FATAL ERROR:\n%s\n", txt);
+
+    if (txt != mybuf)
+        free(txt);
 
+    exit(-123);
 }
diff --git a/command_line/CmdLine/Src/Envir/CLIO.c b/command_line/CmdLine/Src/Envir/CLIO.c
index e832de5..70ba9ae 100644
--- a/command_line/CmdLine/Src/Envir/CLIO.c
+++ b/command_line/CmdLine/Src/Envir/CLIO.c
@@ -1,79 +1,251 @@
-#include "mwcc_decomp.h"
+#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;
 
 static void catchinterrupt() {
-
+    clState.userBreak = 1;
 }
 
 static void SetupConsoleInfo() {
-
+    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;
 }
 
 static void Crash() {
-
+    *((unsigned char *) NULL) = 0;
 }
 
 void SetupDebuggingTraps() {
-
+    signal(SIGABRT, Crash);
 }
 
 Boolean IO_Initialize() {
+    ioPiping = 0;
+    ioInHelp = 0;
+    ioLineNum = 0;
+    SetupConsoleInfo();
 
+    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;
 }
 
 Boolean IO_Terminate() {
-
+    if (ioInHelp)
+        IO_HelpTerminate();
+    TermWorking();
+    return 1;
 }
 
 Boolean IO_HelpInitialize() {
-
+    ioInHelp = 1;
+    return 1;
 }
 
 Boolean IO_HelpTerminate() {
+    ioInHelp = 0;
+    return 1;
+}
+
+static Boolean SendHandleToFile(FILE *file, Handle text, SInt32 size) {
+    Boolean ret;
+    char *ptr;
+    char *lineEnd;
+    char *end;
 
-}
+    if (file != stdout && file != stderr)
+        setvbuf(file, NULL, 0, 1024);
 
-static Boolean SendHandleToFile(FILE *file, OSHandle *text) {
+    HLock(text);
+    ptr = *text;
+    if (size && ptr[size - 1] == 0)
+        size--;
 
+    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;
 }
 
-void FixHandleForIDE(OSHandle *text) {
+void FixHandleForIDE(Handle text, UInt32 size) {
+    char *ptr;
 
+    HLock(text);
+    for (ptr = *text; ptr < (*text + size); ptr++) {
+        if (*ptr == '\r')
+            *ptr = '\n';
+    }
+    HUnlock(text);
 }
 
-Boolean ShowHandle(OSHandle *text, Boolean decorate) {
+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);
 
+    return 1;
 }
 
-Boolean WriteHandleToFile(OSSpec *spec, OSHandle *text, CWDataType creator, CWDataType type) {
+Boolean WriteHandleToFile(OSSpec *spec, Handle text, UInt32 size, OSType creator, OSType type) {
+    FILE *file;
+    char path[256];
 
+    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;
 }
 
 Boolean WriteBinaryHandleToFile(OSSpec *spec, CWDataType maccreator, CWDataType mactype, OSHandle *text) {
+    int err;
+    OSFileHandle file;
 
+    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;
 }
 
-Boolean AppendHandleToFile(OSSpec *spec, OSHandle *text, CWDataType maccreator, CWDataType mactype) {
+Boolean AppendHandleToFile(OSSpec *spec, Handle text, UInt32 size, CWDataType maccreator, CWDataType mactype) {
+    FILE *file;
+    char path[256];
 
-}
+    OS_SpecToString(spec, path, sizeof(path));
+    file = fopen(path, "a+b");
+    if (!file) {
+        CLReportCError(8, errno, path);
+        return 0;
+    }
 
-void InitWorking() {
+    SendHandleToFile(file, text, size);
+    fclose(file);
 
+    OS_SetMacFileCreatorAndType(spec, maccreator, mactype);
+    return 1;
 }
 
-void ShowWorking() {
+void InitWorking() {
+}
 
+void ShowWorking(int x) {
 }
 
 void TermWorking() {
-
 }
 
 static void ProgressFunction(const char *functionname) {
-
+    if (optsCmdLine.verbose)
+        CLReport(7, functionname);
 }
 
 Boolean CheckForUserBreak() {
-
+    ShowWorking(4);
+    return clState.userBreak;
 }
 
 typedef struct {
@@ -81,90 +253,650 @@ typedef struct {
     int pos;
     int maxlen;
     SInt16 col;
-    Boolean origina;
+    Boolean original;
     char *newline;
 } UnkCLIOStruct;
 
+// unknown names for these inlines
+inline void appendText(UnkCLIOStruct *f, const char *str) {
+    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;
+}
+inline void appendChar(UnkCLIOStruct *f, char c) {
+    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++;
+}
+
 static void StartLine(UnkCLIOStruct *f) {
+    f->col = 0;
+    if (!optsEnvir.underIDE && f->newline)
+        appendText(f, f->newline);
+}
 
+inline void newLine(UnkCLIOStruct *f) {
+    if (f->newline)
+        appendChar(f, '\n');
+    else
+        appendChar(f, ' ');
+    StartLine(f);
 }
 
 static void WrapText(UnkCLIOStruct *f) {
-
+    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]);
+    }
 }
 
 static char *IO_VFormatText(char *buffer, SInt32 size, char *newline, const char *format, va_list ap) {
-
+    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;
 }
 
 char *IO_FormatText(char *buffer, SInt32 size, char *newline, const char *format, ...) {
-
-}
-
-void CLPrintDispatch(SInt16 msgtype, const char *message, FILE *out, char *ptr, char *nptr) {
-
+    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;
+
+    if (optsCmdLine.stderr2stdout == 1 || msgtype == Msg_Note || msgtype == Msg_Status) {
+        out = stdout;
+    } else if (msgtype == Msg_Warning || msgtype == Msg_Error || msgtype == Msg_Alert) {
+        out = stderr;
+    } else {
+#line 847
+        OPTION_ASSERT(0);
+    }
+
+    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);
 }
 
 static void GetFileInfo(MessageRef *ref) {
-
+    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;
+        }
+    }
 }
 
 static char *Arrows(MessageRef *ref) {
-
+    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;
 }
 
 static Boolean IsLikelyAnImporter(Plugin *plugin) {
+    if (Plugin_CL_GetObjectFlags(plugin)->flags & 0x80000000)
+        return 0;
 
+    return plugin != Plugins_CL_MatchTarget(NULL, gTarg->cpu, gTarg->os, clState.plugintype, clState.language);
 }
 
 static char *GuessTool(Plugin *plugin) {
-
+    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";
 }
 
 static char *GuessDoing(Plugin *plugin) {
-
-}
-
-static void styledMessage_MPW(Plugin *plugin, MessageRef *ref, SInt16 msgType, const char *format, va_list va) {
-
-}
-
-static void styledMessage_Default(Plugin *plugin, MessageRef *ref, SInt16 msgType, const char *format, va_list va) {
-
-}
-
-static void styledMessage_Terse(Plugin *plugin, MessageRef *ref, SInt16 msgType, const char *format, va_list va) {
-
-}
-
-static void styledMessage_IDE(Plugin *plugin, MessageRef *ref, SInt16 msgType, const char *format, va_list va) {
-
-}
-
-static void styledMessage_Parseable(Plugin *plugin, MessageRef *ref, SInt16 msgType, const char *format, va_list va) {
-
-}
-
-void CLPrintType(SInt16 msgtype, ...) {
-
+    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);
 }
 
 void CLPrint(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, Msg_Note, ptr);
+    if (ptr != printbuffer)
+        free(ptr);
 }
 
 void CLPrintWarning(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, Msg_Warning, ptr);
+    if (ptr != printbuffer)
+        free(ptr);
 }
 
 void CLPrintErr(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, Msg_Error, ptr);
+    if (ptr != printbuffer)
+        free(ptr);
 }
 
 static void FixupMessageRef(MessageRef *ref) {
-
-}
-
-SInt16 CLStyledMessageDispatch(Plugin *plugin, MessageRef *ref, SInt32 errorNumber, SInt16 msgType) {
-
+    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) {
+                CLReport(70);
+                clState.userBreak = 1;
+            } else {
+                CLReport(71);
+            }
+        }
+    }
+
+    if (msgType == Msg_Warning && optsCmdLine.maxWarnings) {
+        if (++clState.countWarnings >= optsCmdLine.maxWarnings) {
+            clState.withholdWarnings = 1;
+            CLReport(72);
+        }
+    }
+
+    return msgType;
 }
-- 
cgit v1.2.3