1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "glk/tads/tads2/error.h"
24 #include "glk/tads/tads2/error_handling.h"
25 #include "glk/tads/tads2/tokenizer.h"
26 
27 namespace Glk {
28 namespace TADS {
29 namespace TADS2 {
30 
31 /* format an error message, sprintf-style, using an erradef array */
errfmt(char * outbuf,int outbufl,const char * fmt,int argc,const erradef * argv)32 int errfmt(char *outbuf, int outbufl, const char *fmt, int argc, const erradef *argv) {
33     int    outlen = 0;
34     int    argi   = 0;
35     int    len = 0;
36     char   buf[20];
37 	const char  *p = nullptr;
38     char   fmtchar;
39 
40     while (*fmt)
41     {
42         switch(*fmt)
43         {
44         case '\\':
45             ++fmt;
46             len = 1;
47             switch(*fmt)
48             {
49             case '\0':
50                 --fmt;
51                 break;
52             case '\n':
53                 p = "\n";
54                 break;
55             case '\t':
56                 p = "\t";
57                 break;
58             default:
59                 p = fmt;
60                 break;
61             }
62             break;
63 
64         case '%':
65             ++fmt;
66             fmtchar = *fmt;
67             if (argi >= argc) fmtchar = 1;          /* too many - ignore it */
68             switch(fmtchar)
69             {
70             case '\0':
71                 --fmt;
72                 break;
73 
74             case '%':
75                 p = "%";
76                 len = 1;
77                 break;
78 
79             case 'd':
80                 sprintf(buf, "%d", argv[argi].erraint);
81                 len = strlen(buf);
82                 p = buf;
83                 break;
84 
85             case 's':
86                 p = argv[argi].errastr;
87                 len = strlen(p);
88                 break;
89 
90             case 't':
91                 {
92                     int i;
93                     static struct
94                     {
95                         int   tokid;
96                         const char *toknam;
97                     } toklist[] =
98                     {
99                         { TOKTSEM, "semicolon" },
100                         { TOKTCOLON, "colon" },
101                         { TOKTFUNCTION, "\"function\"" },
102                         { TOKTCOMMA, "comma" },
103                         { TOKTLBRACE, "left brace ('{')" },
104                         { TOKTRPAR, "right paren (')')" },
105                         { TOKTRBRACK, "right square bracket (']')" },
106                         { TOKTWHILE, "\"while\"" },
107                         { TOKTLPAR, "left paren ('(')" },
108                         { TOKTEQ, "'='" },
109                         { 0, (const char *)nullptr }
110                     };
111 
112                     for (i = 0 ; toklist[i].toknam ; ++i)
113                     {
114                         if (toklist[i].tokid == argv[argi].erraint)
115                         {
116                             p = toklist[i].toknam;
117                             break;
118                         }
119                     }
120                     if (!toklist[i].toknam)
121                         p = "<unknown token>";
122                     len = strlen(p);
123                     break;
124                 }
125 
126             default:
127                 p = "";
128                 len = 0;
129                 --argi;
130                 break;
131             }
132             ++argi;
133             break;
134 
135         default:
136             p = fmt;
137             len = 1;
138             break;
139         }
140 
141         /* copy output that was set up above */
142         if (len)
143         {
144             if (outbufl >= len)
145             {
146                 memcpy(outbuf, p, (size_t)len);
147                 outbufl -= len;
148                 outbuf += len;
149             }
150             else if (outbufl)
151             {
152                 memcpy(outbuf, p, (size_t)outbufl);
153                 outbufl = 0;
154             }
155             outlen += len;
156         }
157         ++fmt;
158     }
159 
160     if (outbufl) *outbuf++ = '\0';
161     return(outlen);
162 }
163 
164 #ifdef DEBUG
165 void errjmp(buf, e)
166 jmp_buf buf;
167 int     e;
168 {
169     longjmp(buf, e);
170 }
171 #endif /* DEBUG */
172 
173 
174 
175 #ifdef ERR_NO_MACRO
176 
177 /* base error signal function */
errsign(errcxdef * ctx,int e)178 void errsign(errcxdef *ctx, int e) {
179     ctx->errcxofs = 0;
180 #if 0
181 	longjmp(ctx->errcxptr->errbuf, e);
182 #else
183 	error("errsign");
184 #endif
185 }
186 
187 /* log an error: base function */
errlogn(errcxdef * ctx,int err)188 void errlogn(errcxdef *ctx, int err) {
189 	error("errlogn");
190 }
191 
192 #endif /* ERR_NO_MACRO */
193 
194 } // End of namespace TADS2
195 } // End of namespace TADS
196 } // End of namespace Glk
197