Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / ilasm / scanner / StringHelper.cs
1 // StringHelper.cs\r
2 // Author: Sergey Chaban (serge@wildwestsoftware.com)\r
3 \r
4 using System;\r
5 using System.Text;\r
6 \r
7 namespace Mono.ILASM {\r
8 \r
9         /// <summary>\r
10         /// </summary>\r
11         internal class StringHelper : StringHelperBase {\r
12 \r
13                 private static readonly string startIdChars = "#$@_";\r
14                 private static readonly string idChars = "_$@?`";\r
15 \r
16                 /// <summary>\r
17                 /// </summary>\r
18                 /// <param name="host"></param>\r
19                 public StringHelper (ILTokenizer host) : base (host)\r
20                 {\r
21                 }\r
22 \r
23 \r
24                 /// <summary>\r
25                 /// </summary>\r
26                 /// <returns></returns>\r
27                 public override bool Start (char ch)\r
28                 {\r
29                         mode = Token.UNKNOWN;\r
30 \r
31                         if (Char.IsLetter (ch) || startIdChars.IndexOf (ch) != -1) {\r
32                                 mode = Token.ID;\r
33                         } else if (ch == '\'') {\r
34                                 mode = Token.SQSTRING;\r
35                         } else if (ch == '"') {\r
36                                 mode = Token.QSTRING;\r
37                         }\r
38 \r
39                         return (mode != Token.UNKNOWN);\r
40                 }\r
41 \r
42 \r
43                 private static bool IsIdChar (int c)\r
44                 {\r
45                         char ch = (char) c;\r
46                         return (Char.IsLetterOrDigit(ch) || idChars.IndexOf (ch) != -1);\r
47                 }\r
48 \r
49                 /// <summary>\r
50                 /// </summary>\r
51                 /// <returns></returns>\r
52                 public override string Build ()\r
53                 {\r
54                         if (mode == Token.UNKNOWN) return String.Empty;\r
55                         int ch = 0;\r
56 \r
57                         ILReader reader = host.Reader;\r
58 \r
59                         StringBuilder idsb = new StringBuilder ();\r
60                         if (mode == Token.SQSTRING || mode == Token.QSTRING) {\r
61                                 int term = (mode == Token.SQSTRING) ? '\'' : '"';\r
62                                 reader.Read (); // skip quote\r
63                                 for (ch = reader.Read (); ch != -1; ch = reader.Read ()) {\r
64                                         if (ch == term) {\r
65                                                 break;\r
66                                         }\r
67 \r
68                                         if (ch == '\\') {\r
69                                                 ch = reader.Read ();\r
70 \r
71                                                 /*\r
72                                                  * Long string can be broken across multiple lines\r
73                                                  * by using '\' as the last char in line.\r
74                                                  * Any white space chars between '\' and the first\r
75                                                  * char on the next line are ignored.\r
76                                                  */\r
77                                                 if (ch == '\n') {\r
78                                                         reader.SkipWhitespace ();\r
79                                                         continue;\r
80                                                 }\r
81 \r
82                                                 int escaped = Escape (reader, ch);\r
83                                                 if (escaped == -1) {\r
84                                                         reader.Unread (ch);\r
85                                                         ch = '\\';\r
86                                                 } else {\r
87                                                         ch = escaped;\r
88                                                 }\r
89                                         }\r
90 \r
91                                         idsb.Append((char)ch);\r
92                                 }\r
93                         } else { // ID\r
94                                 while ((ch = reader.Read ()) != -1) {\r
95                                         if (IsIdChar (ch)) {\r
96                                                 idsb.Append ((char) ch);\r
97                                         } else {\r
98                                                 reader.Unread (ch);\r
99                                                 break;\r
100                                         }\r
101                                 }\r
102                         }\r
103                         return idsb.ToString ();\r
104                 }\r
105 \r
106 \r
107 \r
108 \r
109                 /// <summary>\r
110                 /// </summary>\r
111                 /// <param name="ch"></param>\r
112                 /// <returns></returns>\r
113                 public static int Escape (ILReader reader, int ch)\r
114                 {\r
115                         int res = -1;\r
116 \r
117                         if (ch >= '0' && ch <='7') {\r
118                                 StringBuilder octal = new StringBuilder ();\r
119                                 octal.Append ((char)ch);\r
120                                 int possibleOctalChar = reader.Peek ();\r
121                                 if (possibleOctalChar >= '0' && possibleOctalChar <='7') {\r
122                                         octal.Append ((char)reader.Read ());\r
123                                         possibleOctalChar = reader.Peek ();\r
124                                         if (possibleOctalChar >= '0' && possibleOctalChar <='7')\r
125                                                 octal.Append ((char)reader.Read ());\r
126                                 }\r
127                                 res = Convert.ToInt32(octal.ToString (), 8);\r
128                         } else {\r
129                                 int id = "abfnrtv\"'\\".IndexOf ((char)ch);\r
130                                 if (id != -1) {\r
131                                         res = "\a\b\f\n\r\t\v\"'\\" [id];\r
132                                 }\r
133                         }\r
134 \r
135                         return res;\r
136                 }\r
137 \r
138         }\r
139 \r
140 \r
141 }\r
142 \r