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 
165 #ifdef ERR_NO_MACRO
166 
167 /* base error signal function */
errsign(errcxdef * ctx,int e)168 void errsign(errcxdef *ctx, int e) {
169 	ctx->errcxofs = 0;
170 #if 0
171 	longjmp(ctx->errcxptr->errbuf, e);
172 #else
173 	error("errsign");
174 #endif
175 }
176 
177 /* log an error: base function */
errlogn(errcxdef * ctx,int err)178 void errlogn(errcxdef *ctx, int err) {
179 	error("errlogn");
180 }
181 
182 #endif /* ERR_NO_MACRO */
183 
184 } // End of namespace TADS2
185 } // End of namespace TADS
186 } // End of namespace Glk
187