1 
2 /******************************************************************************
3 * MODULE     : string.cpp
4 * DESCRIPTION: Fixed size strings with reference counting.
5 *              Zero characters can be part of string.
6 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
7 *******************************************************************************
8 * This software falls under the GNU general public license version 3 or later.
9 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
10 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ******************************************************************************/
12 
13 #include "string.hpp"
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17 
18 /******************************************************************************
19 * Low level routines and constructors
20 ******************************************************************************/
21 
22 static inline int
round_length(int n)23 round_length (int n) {
24   n=(n+3)&(0xfffffffc);
25   if (n<24) return n;
26   register int i=32;
27   while (n>i) i<<=1;
28   return i;
29 }
30 
string_rep(int n2)31 string_rep::string_rep (int n2):
32   n(n2), a ((n==0)?((char*) NULL):tm_new_array<char> (round_length(n))) {}
33 
34 void
resize(register int m)35 string_rep::resize (register int m) {
36   register int nn= round_length (n);
37   register int mm= round_length (m);
38   if (mm != nn) {
39     if (mm != 0) {
40       register int i, k= (m<n? m: n);
41       char* b= tm_new_array<char> (mm);
42       for (i=0; i<k; i++) b[i]= a[i];
43       if (nn != 0) tm_delete_array (a);
44       a= b;
45     }
46     else if (nn != 0) tm_delete_array (a);
47   }
48   n= m;
49 }
50 
string(char c)51 string::string (char c) {
52   rep= tm_new<string_rep> (1);
53   rep->a[0]=c;
54 }
55 
string(char c,int n)56 string::string (char c, int n) {
57   rep= tm_new<string_rep> (n);
58   for (int i=0; i<n; i++)
59     rep->a[i]=c;
60 }
61 
string(const char * a)62 string::string (const char* a) {
63   int i, n=strlen(a);
64   rep= tm_new<string_rep> (n);
65   for (i=0; i<n; i++)
66     rep->a[i]=a[i];
67 }
68 
string(const char * a,int n)69 string::string (const char* a, int n) {
70   register int i;
71   rep= tm_new<string_rep> (n);
72   for (i=0; i<n; i++)
73     rep->a[i]=a[i];
74 }
75 
76 /******************************************************************************
77 * Common routines for strings
78 ******************************************************************************/
79 
80 bool
operator ==(const char * s)81 string::operator == (const char* s) {
82   register int i, n= rep->n;
83   register char* S= rep->a;
84   for (i=0; i<n; i++) {
85     if (s[i]!=S[i]) return false;
86     if (s[i]=='\0') return false;
87   }
88   return (s[i]=='\0');
89 }
90 
91 bool
operator !=(const char * s)92 string::operator != (const char* s) {
93   register int i, n= rep->n;
94   register char* S= rep->a;
95   for (i=0; i<n; i++) {
96     if (s[i]!=S[i]) return true;
97     if (s[i]=='\0') return true;
98   }
99   return (s[i]!='\0');
100 }
101 
102 bool
operator ==(string a)103 string::operator == (string a) {
104   register int i;
105   if (rep->n!=a->n) return false;
106   for (i=0; i<rep->n; i++)
107     if (rep->a[i]!=a->a[i]) return false;
108   return true;
109 }
110 
111 bool
operator !=(string a)112 string::operator != (string a) {
113   register int i;
114   if (rep->n!=a->n) return true;
115   for (i=0; i<rep->n; i++)
116     if (rep->a[i]!=a->a[i]) return true;
117   return false;
118 }
119 
120 string
operator ()(int begin,int end)121 string::operator () (int begin, int end) {
122   register int i;
123   string r (end-begin);
124   for (i=begin; i<end; i++) r[i-begin]=rep->a[i];
125   return r;
126 }
127 
128 string
copy(string s)129 copy (string s) {
130   register int i, n=N(s);
131   string r (n);
132   for (i=0; i<n; i++) r[i]=s[i];
133   return r;
134 }
135 
136 string&
operator <<(string & a,char x)137 operator << (string& a, char x) {
138   a->resize (N(a)+ 1);
139   a [N(a)-1]=x;
140   return a;
141 }
142 
143 string&
operator <<(string & a,string b)144 operator << (string& a, string b) {
145   register int i, k1= N(a), k2=N(b);
146   a->resize (k1+k2);
147   for (i=0; i<k2; i++) a[i+k1]= b[i];
148   return a;
149 }
150 
151 string
operator *(string a,string b)152 operator * (string a, string b) {
153   register int i, n1=N(a), n2=N(b);
154   string c(n1+n2);
155   for (i=0; i<n1; i++) c[i]=a[i];
156   for (i=0; i<n2; i++) c[i+n1]=b[i];
157   return c;
158 }
159 
160 string
operator *(const char * a,string b)161 operator * (const char* a, string b) {
162   return string (a) * b;
163 }
164 
165 string
operator *(string a,const char * b)166 operator * (string a, const char* b) {
167   return a * string (b);
168 }
169 
170 bool
operator <(string s1,string s2)171 operator < (string s1, string s2) {
172   register int i;
173   for (i=0; i<N(s1); i++) {
174     if (i>=N(s2)) return false;
175     if (s1[i]<s2[i]) return true;
176     if (s2[i]<s1[i]) return false;
177   }
178   return i<N(s2);
179 }
180 
181 bool
operator <=(string s1,string s2)182 operator <= (string s1, string s2) {
183   register int i;
184   for (i=0; i<N(s1); i++) {
185     if (i>=N(s2)) return false;
186     if (s1[i]<s2[i]) return true;
187     if (s2[i]<s1[i]) return false;
188   }
189   return true;
190 }
191 
192 tm_ostream&
operator <<(tm_ostream & out,string a)193 operator << (tm_ostream& out, string a) {
194   int i, n=N(a);
195   if (n==0) return out;
196   for (i=0; i<n; i++) out << a[i];
197   return out;
198 }
199 
200 int
hash(string s)201 hash (string s) {
202   register int i, h=0, n=N(s);
203   for (i=0; i<n; i++) {
204     h=(h<<9)+(h>>23);
205     h=h+((int) s[i]);
206   }
207   return h;
208 }
209 
210 /******************************************************************************
211 * Conversion routines
212 ******************************************************************************/
213 
214 bool
as_bool(string s)215 as_bool (string s) {
216   return (s == "true" || s == "#t");
217 }
218 
219 int
as_int(string s)220 as_int (string s) {
221   int i=0, n=N(s), val=0;
222   if (n==0) return 0;
223   if (s[0]=='-') i++;
224   while (i<n) {
225     if (s[i]<'0') break;
226     if (s[i]>'9') break;
227     val *= 10;
228     val += (int) (s[i]-'0');
229     i++;
230   }
231   if (s[0]=='-') val=-val;
232   return val;
233 }
234 
235 
236 long int
as_long_int(string s)237 as_long_int (string s) {
238   int i=0, n=N(s);
239   long int val=0;
240   if (n==0) return 0;
241   if (s[0]=='-') i++;
242   while (i<n) {
243     if (s[i]<'0') break;
244     if (s[i]>'9') break;
245     val *= 10;
246     val += (int) (s[i]-'0');
247     i++;
248   }
249   if (s[0]=='-') val=-val;
250   return val;
251 }
252 
253 double
as_double(string s)254 as_double (string s) {
255   double x= 0.0;
256   {
257     int i, n= N(s);
258     STACK_NEW_ARRAY (buf, char, n+1);
259     for (i=0; i<n; i++) buf[i]=s[i];
260     buf[n]='\0';
261     sscanf (buf, "%lf", &x);
262     STACK_DELETE_ARRAY (buf);
263   } // in order to avoid segmentation fault due to compiler bug
264   return x;
265 }
266 
267 char*
as_charp(string s)268 as_charp (string s) {
269   int i, n= N(s);
270   char *s2= tm_new_array<char> (n+1);
271   for (i=0; i<n; i++) s2[i]=s[i];
272   s2[n]= '\0';
273   return s2;
274 }
275 
276 string
as_string_bool(bool f)277 as_string_bool (bool f) {
278   if (f) return string ("true");
279   else return string ("false");
280 }
281 
282 string
as_string(int i)283 as_string (int i) {
284   char buf[64];
285   sprintf (buf, "%i", i);
286   // sprintf (buf, "%i\0", i);
287   return string (buf);
288 }
289 
290 string
as_string(unsigned int i)291 as_string (unsigned int i) {
292   char buf[64];
293   sprintf (buf, "%u", i);
294   // sprintf (buf, "%u\0", i);
295   return string (buf);
296 }
297 
298 string
as_string(long int i)299 as_string (long int i) {
300   char buf[64];
301   sprintf (buf, "%li", i);
302   // sprintf (buf, "%li\0", i);
303   return string (buf);
304 }
305 
306 string
as_string(long long int i)307 as_string (long long int i) {
308   char buf[64];
309 #if defined (__MINGW__) || defined (__MINGW32__)
310   sprintf (buf, "%I64d", i);
311 #else
312   sprintf (buf, "%lli", i);
313 #endif
314   // sprintf (buf, "%lli\0", i);
315   return string (buf);
316 }
317 
318 string
as_string(unsigned long int i)319 as_string (unsigned long int i) {
320   char buf[64];
321   sprintf (buf, "%lu", i);
322   // sprintf (buf, "%lu\0", i);
323   return string (buf);
324 }
325 
326 string
as_string(double x)327 as_string (double x) {
328   char buf[64];
329   sprintf (buf, "%g", x);
330   // sprintf (buf, "%g\0", x);
331   return string(buf);
332 }
333 
334 string
as_string(const char * s)335 as_string (const char* s) {
336   return string (s);
337 }
338 
339 bool
is_bool(string s)340 is_bool (string s) {
341   return (s == "true") || (s == "false");
342 }
343 
344 bool
is_int(string s)345 is_int (string s) {
346   int i=0, n=N(s);
347   if (n==0) return false;
348   if (s[i]=='+') i++;
349   if (s[i]=='-') i++;
350   if (i==n) return false;
351   for (; i<n; i++)
352     if ((s[i]<'0') || (s[i]>'9')) return false;
353   return true;
354 }
355 
356 bool
is_double(string s)357 is_double (string s) {
358   int i=0, n=N(s);
359   if (n==0) return false;
360   if (s[i]=='+') i++;
361   if (s[i]=='-') i++;
362   if (i==n) return false;
363   for (; i< n; i++)
364     if ((s[i]<'0') || (s[i]>'9')) break;
365   if (i==n) return true;
366   if (s[i]=='.') {
367     i++;
368     if (i==n) return false;
369     for (; i< n; i++)
370       if ((s[i]<'0') || (s[i]>'9')) break;
371   }
372   if (i==n) return true;
373   if (s[i++]!='e') return false;
374   if (s[i]=='+') i++;
375   if (s[i]=='-') i++;
376   if (i==n) return false;
377   for (; i< n; i++)
378     if ((s[i]<'0') || (s[i]>'9')) return false;
379   return true;
380 }
381 
382 bool
is_charp(string s)383 is_charp (string s) { (void) s;
384   return true;
385 }
386 
387 bool
is_quoted(string s)388 is_quoted (string s) {
389   return (N(s)>=2) && (s[0]=='\042') && (s[N(s)-1]=='\042');
390 }
391 
392 bool
is_id(string s)393 is_id (string s) {
394   int i=0, n=N(s);
395   if (n==0) return false;
396   for (i=0; i< n; i++) {
397     if ((i>0) && (s[i]>='0') && (s[i]<='9')) continue;
398     if ((s[i]>='a') && (s[i]<='z')) continue;
399     if ((s[i]>='A') && (s[i]<='Z')) continue;
400     if (s[i]=='_') continue;
401     return false;
402   }
403   return true;
404 }
405 
406 /******************************************************************************
407 * Error messages
408 ******************************************************************************/
409 
410 static void (*the_wait_handler) (string, string, int) = NULL;
411 
412 void
set_wait_handler(void (* routine)(string,string,int))413 set_wait_handler (void (*routine) (string, string, int)) {
414   the_wait_handler= routine; }
415 
416 void
system_wait(string message,string argument,int level)417 system_wait (string message, string argument, int level) {
418   if (the_wait_handler == NULL) {
419     if (DEBUG_AUTO) {
420       if (message == "") cout << "TeXmacs] Done" << LF;
421       else {
422 	if (argument == "") cout << "TeXmacs] " << message << LF;
423 	else cout << "TeXmacs] " << message << " " << argument << LF;
424 	cout << "TeXmacs] Please wait..." << LF;
425       }
426     }
427   }
428   else the_wait_handler (message, argument, level);
429 }
430