Sun, 02 Feb 2014 17:06:39 +0200
- reformatting
88 | 1 | /* |
2 | Copyright 2012-2014 Santeri Piippo | |
3 | All rights reserved. | |
4 | ||
5 | Redistribution and use in source and binary forms, with or without | |
6 | modification, are permitted provided that the following conditions | |
7 | are met: | |
8 | ||
9 | 1. Redistributions of source code must retain the above copyright | |
10 | notice, this list of conditions and the following disclaimer. | |
11 | 2. Redistributions in binary form must reproduce the above copyright | |
12 | notice, this list of conditions and the following disclaimer in the | |
13 | documentation and/or other materials provided with the distribution. | |
14 | 3. The name of the author may not be used to endorse or promote products | |
15 | derived from this software without specific prior written permission. | |
16 | ||
17 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
18 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
20 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
22 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | #include <cstdio> | |
30 | #include "Main.h" | |
31 | #include "Format.h" | |
32 | #include "Lexer.h" | |
33 | ||
34 | // ============================================================================= | |
35 | // | |
36 | static void DrawPosition (const String& fmt, int pos) | |
37 | { | |
38 | String rep (fmt); | |
39 | rep.Replace ("\n", "↵"); | |
40 | rep.Replace ("\t", "⇥"); | |
41 | ||
42 | fprintf (stderr, "%s\n", rep.CString()); | |
43 | ||
44 | for (int x = 0; x < pos; ++x) | |
45 | fprintf (stderr, "-"); | |
46 | ||
47 | fprintf (stderr, "^\n"); | |
48 | } | |
49 | ||
50 | // ============================================================================= | |
51 | // | |
52 | String FormatArgs (const List<FormatArgument>& args) | |
53 | { | |
54 | const String& fmtstr = args[0].AsString(); | |
55 | assert (args.Size() >= 1); | |
56 | ||
57 | if (args.Size() == 1) | |
58 | return args[0].AsString(); | |
59 | ||
60 | String fmt = fmtstr; | |
61 | String out; | |
62 | int pos = 0; | |
63 | ||
64 | while ((pos = fmt.FirstIndexOf ("%", pos)) != -1) | |
65 | { | |
66 | if (fmt[pos + 1] == '%') | |
67 | { | |
68 | fmt.Replace (pos, 2, "%"); | |
69 | pos++; | |
70 | continue; | |
71 | } | |
72 | ||
73 | int ofs = 1; | |
74 | char mod = '\0'; | |
75 | ||
76 | // handle modifiers | |
77 | if (fmt[pos + ofs] == 's' || fmt[pos + ofs] == 'x') | |
78 | { | |
79 | mod = fmt[pos + ofs]; | |
80 | ofs++; | |
81 | } | |
82 | ||
83 | if (!isdigit (fmt[pos + ofs])) | |
84 | { | |
85 | fprintf (stderr, "bad format string, expected digit with optional " | |
86 | "modifier after '%%':\n"); | |
87 | DrawPosition (fmt, pos); | |
88 | return fmt; | |
89 | } | |
90 | ||
91 | int i = fmt[pos + ofs] - '0'; | |
92 | ||
93 | if (i >= args.Size()) | |
94 | { | |
95 | fprintf (stderr, "format arg #%d used but not defined: %s\n", i, fmtstr.CString()); | |
96 | return fmt; | |
97 | } | |
98 | ||
99 | String repl = args[i].AsString(); | |
100 | ||
101 | switch (mod) | |
102 | { | |
103 | case 's': repl = (repl == "1") ? "" : "s"; break; | |
104 | case 'd': repl.SPrintf ("%d", repl[0]); break; | |
105 | case 'x': repl.SPrintf ("0x%X", repl.ToLong()); break; | |
106 | default: break; | |
107 | } | |
108 | ||
109 | fmt.Replace (pos, 1 + ofs, repl); | |
110 | pos += repl.Length(); | |
111 | } | |
112 | ||
113 | return fmt; | |
114 | } | |
115 | ||
116 | // ============================================================================= | |
117 | // | |
118 | void PrintArgs (FILE* fp, const List<FormatArgument>& args) | |
119 | { | |
120 | String out = FormatArgs (args); | |
121 | fprintf (fp, "%s", out.CString()); | |
122 | } | |
123 | ||
124 | // ============================================================================= | |
125 | // | |
126 | void DoError (String msg) | |
127 | { | |
128 | Lexer* lx = Lexer::GetCurrentLexer(); | |
129 | String fileinfo; | |
130 | ||
131 | if (lx != null && lx->HasValidToken()) | |
132 | { | |
133 | Lexer::Token* tk = lx->GetToken(); | |
134 | fileinfo = Format ("%1:%2:%3: ", tk->file, tk->line, tk->column); | |
135 | } | |
136 | ||
137 | throw ScriptError (fileinfo + msg); | |
138 | } |