OSDN Git Service

Version 5.93
[vbslib/main.git] / _src / Test / tools / vbslib_helper_src / clib.c
1 /* Character Code Encoding: "WHITE SQUARE" is \81  */\r
2 /* The source file was composed by module mixer */ \r
3 \r
4 #include  "include_c.h"\r
5 \r
6 \r
7  \r
8 /*=================================================================*/\r
9 /* <<< [Global0/Global0.c] >>> */ \r
10 /*=================================================================*/\r
11  \r
12 /***********************************************************************\r
13   <<< [Globals_initConst] >>> \r
14 ************************************************************************/\r
15 \r
16 void  Globals_initConst()\r
17 {\r
18     AppKey_initGlobal_const(); \r
19 }\r
20 \r
21 \r
22  \r
23 /***********************************************************************\r
24   <<< [Globals_initialize] >>> \r
25 ************************************************************************/\r
26 int  Globals_initialize()\r
27 {\r
28   int  e;\r
29 \r
30     e= Locale_init(); IF(e)goto fin;\r
31 \r
32   e=0;\r
33   goto fin;  // for avoid warning of no goto fin\r
34 fin:\r
35   return  e;\r
36 }\r
37 \r
38 \r
39  \r
40 /***********************************************************************\r
41   <<< [Globals_finalize] >>> \r
42 ************************************************************************/\r
43 int  Globals_finalize( int e )\r
44 {\r
45     HeapLogClass_finalize();\r
46     e= AppKey_finishGlobal( e ); \r
47 \r
48   return  e;\r
49 }\r
50 \r
51 \r
52  \r
53 /*=================================================================*/\r
54 /* <<< [PlatformSDK_plus/PlatformSDK_plus.c] >>> */ \r
55 /*=================================================================*/\r
56  \r
57 /***********************************************************************\r
58   <<< [GetCommandLineUnnamed] >>> \r
59 ************************************************************************/\r
60 int  GetCommandLineUnnamed( int Index1, TCHAR* out_AParam, size_t AParamSize )\r
61 {\r
62         TCHAR*  line = GetCommandLine();\r
63         int     index;\r
64         TCHAR*  p;\r
65         TCHAR*  p2;\r
66         TCHAR   c;\r
67 \r
68         #if UNDER_CE\r
69                 Index1 --;\r
70         #endif\r
71         IF( Index1 < 0 ) goto err_nf;\r
72         index = Index1;\r
73 \r
74         p = line;\r
75 \r
76         for (;;) {\r
77                 while ( *p == _T(' ') )  p++;\r
78 \r
79                 c = *p;\r
80 \r
81                 if ( c == _T('\0') )  goto err_nf;  // Here is not decided to error or not\r
82 \r
83 \r
84                 //=== Skip named option\r
85                 else if ( c == _T('/') ) {\r
86                         p++;\r
87                         for (;;) {\r
88                                 c = *p;\r
89                                 if ( c == _T('"') || c == _T(' ') || c == _T('\0') )  break;\r
90                                 p++;\r
91                         }\r
92 \r
93                         if ( c == _T('"') ) {\r
94                                 p++;\r
95                                 while ( *p != _T('"') && *p != _T('\0') )  p++;\r
96                                 if ( *p == _T('"') )  p++;\r
97                         }\r
98                 }\r
99 \r
100                 //=== Skip or Get unnamed parameter\r
101                 else {\r
102                         while ( *p == _T(' ') )  p++;\r
103 \r
104                         c = *p;\r
105                         p2 = p + 1;\r
106 \r
107                         if ( c == _T('"') ) {\r
108                                 p ++;\r
109                                 while ( *p2 != _T('"') && *p2 != _T('\0') )  p2++;\r
110                         }\r
111                         else {\r
112                                 while ( *p2 != _T(' ') && *p2 != _T('\0') )  p2++;\r
113                         }\r
114 \r
115                         if ( index == 0 ) {\r
116                                 int  e;\r
117 \r
118                                 e= stcpy_part_r( out_AParam, AParamSize, out_AParam, NULL, p, p2 );\r
119                                         ASSERT_D( !e, __noop() );\r
120                                 return  e;\r
121                         }\r
122                         else {\r
123                                 p = ( *p2 == _T('"') ) ? p2+1 : p2;\r
124                                 index --;\r
125                         }\r
126                 }\r
127         }\r
128 \r
129 err_nf:\r
130         if ( AParamSize >= sizeof(TCHAR) )  *out_AParam = _T('\0');\r
131         IF ( Index1 >= 2 )  return  E_NOT_FOUND_SYMBOL;\r
132         return  0;\r
133 }\r
134 \r
135 \r
136  \r
137 /***********************************************************************\r
138   <<< [GetCommandLineNamed] >>> \r
139 ************************************************************************/\r
140 int  GetCommandLineNamed_sub( const TCHAR* Name, bool bCase, bool* out_IsExist, TCHAR* out_Value, size_t ValueSize );\r
141 \r
142 int  GetCommandLineNamed( const TCHAR* Name, bool bCase, TCHAR* out_Value, size_t ValueSize )\r
143 {\r
144         bool  is_exist;\r
145         return  GetCommandLineNamed_sub( Name, bCase, &is_exist, out_Value, ValueSize );\r
146 }\r
147 \r
148 \r
149 int  GetCommandLineNamed_sub( const TCHAR* Name, bool bCase, bool* out_IsExist, TCHAR* out_Value, size_t ValueSize )\r
150 {\r
151         TCHAR*  line = GetCommandLine();\r
152         TCHAR*  p;\r
153         TCHAR*  p2;\r
154         TCHAR   c;\r
155         const size_t  name_len = _tcslen( Name );\r
156         bool    bMatch;\r
157 \r
158         *out_IsExist = true;\r
159 \r
160         p = line;\r
161         for (;;) {\r
162                 c = *p;\r
163 \r
164                 //=== Compare option name\r
165                 if ( c == _T('/') ) {\r
166                         p++;\r
167                         p2 = p;\r
168                         for (;;) {\r
169                                 c = *p2;\r
170                                 if ( c == _T(':') || c == _T(' ') || c == _T('\0') )  break;\r
171                                 p2++;\r
172                         }\r
173                         if ( bCase )\r
174                                 bMatch = ( p2-p == (int)name_len && _tcsncmp( p, Name, p2-p ) == 0 );\r
175                         else\r
176                                 bMatch = ( p2-p == (int)name_len && _tcsnicmp( p, Name, p2-p ) == 0 );\r
177 \r
178 \r
179                         //=== Get the value\r
180                         if ( c == _T(':') ) {\r
181                                 p = p2 + 1;\r
182                                 if ( *p == _T('"') ) {\r
183                                         p++;\r
184                                         p2 = p;\r
185                                         while ( *p2 != _T('"') && *p2 != _T('\0') )  p2++;\r
186                                         if ( bMatch )\r
187                                                 return  stcpy_part_r( out_Value, ValueSize, out_Value, NULL, p, p2 );\r
188                                         else\r
189                                                 p = p2+1;\r
190                                 }\r
191                                 else {\r
192                                         p2 = p;\r
193                                         while ( *p2 != _T(' ') && *p2 != _T('\0') )  p2++;\r
194                                         if ( bMatch )\r
195                                                 return  stcpy_part_r( out_Value, ValueSize, out_Value, NULL, p, p2 );\r
196                                         else\r
197                                                 p = p2;\r
198                                 }\r
199                         }\r
200                         else {\r
201                                 IF( bMatch ) return  E_NOT_FOUND_SYMBOL;  // no value error\r
202                         }\r
203                 }\r
204 \r
205                 else if ( c == _T('\0') )  break;\r
206 \r
207                 //=== Skip\r
208                 else if ( c == _T('"') ) {\r
209                         p++;\r
210                         while ( *p != _T('"') && *p != _T('\0') )  p++;\r
211                         while ( *p != _T(' ') && *p != _T('\0') )  p++;\r
212                 }\r
213                 else {\r
214                         while ( *p != _T(' ') && *p != _T('\0') )  p++;\r
215                 }\r
216                 while ( *p == _T(' ') )  p++;\r
217         }\r
218 \r
219         *out_IsExist = false;\r
220         return  E_NOT_FOUND_SYMBOL;\r
221 }\r
222 \r
223 \r
224  \r
225 /***********************************************************************\r
226   <<< [GetCommandLineNamedI] >>> \r
227 ************************************************************************/\r
228 int  GetCommandLineNamedI( const TCHAR* Name, bool bCase, int* out_Value )\r
229 {\r
230         int    e;\r
231         bool   is_exist;\r
232         TCHAR  s[20];\r
233 \r
234         e= GetCommandLineNamed_sub( Name, bCase, &is_exist, s, sizeof(s) ); IF(e)goto fin;  //[out] s\r
235         if ( s[0] == _T('0') && s[1] == _T('x') )\r
236                 *out_Value = _tcstoul( s, NULL, 16 );\r
237         else\r
238                 *out_Value = _ttoi( s );\r
239         //e=0;\r
240 fin:\r
241         return  e;\r
242 }\r
243 \r
244 \r
245  \r
246 /***********************************************************************\r
247   <<< [GetCommandLineNamedC8] >>> \r
248 ************************************************************************/\r
249 #if  _UNICODE\r
250 int  GetCommandLineNamedC8( const TCHAR* Name, bool bCase, char* out_Value, size_t ValueSize )\r
251 {\r
252         int     e;\r
253         bool    is_exist;\r
254         TCHAR*  s = NULL;\r
255 \r
256         s = (TCHAR*) malloc( ValueSize * sizeof(TCHAR) );\r
257         e= GetCommandLineNamed_sub( Name, bCase, &is_exist, (TCHAR*) s, ValueSize * sizeof(TCHAR) ); IF(e)goto fin;\r
258 \r
259         sprintf_s( out_Value, ValueSize, "%S", s );\r
260 fin:\r
261         if ( s != NULL )  free( s );\r
262         return  e;\r
263 }\r
264 #endif\r
265 \r
266 \r
267  \r
268 /***********************************************************************\r
269   <<< [GetCommandLineExist] >>> \r
270 ************************************************************************/\r
271 bool  GetCommandLineExist( const TCHAR* Name, bool bCase )\r
272 {\r
273         int     e;\r
274         bool    is_exist;\r
275         TCHAR   v[1];\r
276 \r
277         e = GetCommandLineNamed_sub( Name, bCase, &is_exist, v, sizeof(v) );\r
278         if ( e == E_NOT_FOUND_SYMBOL )  ClearError();\r
279         return  is_exist;\r
280 }\r
281 \r
282 \r
283  \r
284 /***********************************************************************\r
285 * Function: GetProcessInformation\r
286 ************************************************************************/\r
287 errnum_t  GetProcessInformation( DWORD  in_ProcessID,  PROCESSENTRY32*  out_Info )\r
288 {\r
289         errnum_t  e;\r
290         BOOL      b;\r
291         HANDLE    snapshot = (HANDLE) -1;\r
292 \r
293         snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );\r
294                 IF ( snapshot == (HANDLE) -1 ) { e=E_OTHERS; goto fin; }\r
295         b= Process32First( snapshot,  /*Set*/ out_Info );\r
296                 IF (!b) { e=E_OTHERS; goto fin; }\r
297         for (;;) {\r
298                 if ( out_Info->th32ProcessID == in_ProcessID ) {\r
299                         break;\r
300                 }\r
301                 b= Process32Next( snapshot,  /*Set*/ out_Info );\r
302                 IF (!b) { e=E_OTHERS; goto fin; }\r
303         }\r
304 \r
305         e=0;\r
306 fin:\r
307         if ( snapshot != (HANDLE) -1 )  { CloseHandle( snapshot ); }\r
308         return  0;\r
309 }\r
310 \r
311 \r
312  \r
313 /***********************************************************************\r
314   <<< [env_part] >>> \r
315 ************************************************************************/\r
316 int  env_part( TCHAR* Str,  unsigned StrSize,  TCHAR* StrStart, TCHAR** out_StrLast,\r
317          const TCHAR* Input )\r
318 {\r
319         int  e;\r
320         const TCHAR*  p;\r
321         const TCHAR*  p2;\r
322         TCHAR*  o;\r
323         TCHAR*  o_last;\r
324         TCHAR   c;\r
325         DWORD   r;\r
326         DWORD   count;\r
327         TCHAR   name[128];\r
328 \r
329         p = Input;  o = StrStart;  o_last = (TCHAR*)( (char*)Str + StrSize - sizeof(TCHAR) );\r
330         IF_D( StrStart < Str || StrStart >= o_last ) goto err;\r
331 \r
332         c = *p;\r
333         IF_D( StrSize <= 2 ) return  E_FEW_ARRAY;\r
334 \r
335         while ( c != _T('\0') ) {\r
336                 if ( c == _T('%') ) {\r
337                         p++;\r
338                         if ( *p == _T('%') ) {\r
339 \r
340                                 //=== % \95\8e\9a\82ð\83R\83s\81[\82·\82é\r
341                                 IF( o == o_last )goto err_fa;\r
342                                 *o = c;\r
343                                 p++;  o++;\r
344                         }\r
345                         else {\r
346 \r
347                                 //=== \8aÂ\8b«\95Ï\90\94\96¼\82ð name \82É\8eæ\93¾\82·\82é\r
348                                 p2 = _tcschr( p, _T('%') ); IF( p2 == NULL )goto err_ns;\r
349                                 e= StrT_cpy( name, sizeof(name), _T("abc") ); IF(e)goto fin;\r
350                                 e= stcpy_part_r( name, sizeof(name), name, NULL, p, p2 ); IF(e)goto fin;\r
351 \r
352                                 //=== \8aÂ\8b«\95Ï\90\94\82Ì\92l\82ð o \82É\8eæ\93¾\82·\82é\r
353                                 count = ( o_last + sizeof(TCHAR) - o ) / sizeof(TCHAR);\r
354                                 r= GetEnvironmentVariable( name, o, count );\r
355                                 IF( r==0 ) goto err_ns;  // \8aÂ\8b«\95Ï\90\94\82ª\8c©\82Â\82©\82ç\82È\82¢\r
356                                 IF( r > count ) goto err_fa;\r
357 \r
358                                 //=== p, o \82ð\8dX\90V\82·\82é\r
359                                 p = p2 + 1;\r
360                                 o = StrT_chr( o, _T('\0') );\r
361                         }\r
362                 }\r
363                 else {\r
364 \r
365                         //=== \8aÂ\8b«\95Ï\90\94\82Å\82Í\82È\82¢\95\94\95ª\82ð\83R\83s\81[\82·\82é\r
366                         IF( o == o_last )goto err_fa;\r
367                         *o = c;\r
368                         p++;  o++;\r
369                 }\r
370                 c = *p;\r
371         }\r
372 \r
373         e=0;\r
374 fin:\r
375         *o = _T('\0');\r
376         if ( out_StrLast != NULL )  *out_StrLast = o;\r
377         return  e;\r
378 \r
379 err_fa:  e = E_FEW_ARRAY;  goto fin;\r
380 err_ns:  e = E_NOT_FOUND_SYMBOL; goto fin;\r
381 err:  e = E_OTHERS;  goto fin;\r
382 }\r
383 \r
384 \r
385  \r
386 /***********************************************************************\r
387   <<< [env_malloc] >>> \r
388 ************************************************************************/\r
389 int  env_malloc( TCHAR** out_Value, size_t* out_ValueLen, const TCHAR* Name )\r
390 {\r
391         int     e;\r
392         DWORD   r;\r
393         TCHAR*  value = NULL;\r
394 \r
395         r= GetEnvironmentVariable( Name, NULL, 0 );\r
396         if ( r == 0 ) {\r
397                 *out_Value = NULL;\r
398                 return  0;  // \8aÂ\8b«\95Ï\90\94\82ª\92è\8b`\82³\82ê\82Ä\82¢\82È\82¢\82Æ\82«\82Å\82à\81A\83G\83\89\81[\82É\82µ\82È\82¢\r
399         }\r
400 \r
401         value = (TCHAR*) malloc( r * sizeof(TCHAR) );\r
402         IF( value == NULL ) goto err_fm;\r
403         GetEnvironmentVariable( Name, value, r );\r
404 \r
405         *out_Value = value;\r
406         if ( out_ValueLen != NULL )  *out_ValueLen = r - 1;\r
407 \r
408         e=0;\r
409 fin:\r
410         return  e;\r
411 \r
412 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
413 }\r
414 \r
415 \r
416  \r
417 /*=================================================================*/\r
418 /* <<< [Parse2/Parse2.c] >>> */ \r
419 /*=================================================================*/\r
420  \r
421 /***********************************************************************\r
422   <<< [g_NaturalDocsKeywords] >>> \r
423 ************************************************************************/\r
424 TCHAR*  g_NaturalDocsKeywords[] = {\r
425 \r
426         /*===========================================================*/\r
427         /* General Topics */\r
428         /* Generic */\r
429         _T("topic"), _T("topics"), _T("about"), _T("list"),\r
430 \r
431         /* Section (Ends Scope) */\r
432         _T("section"), _T("title"),\r
433 \r
434         /* Group */\r
435         _T("group"),\r
436 \r
437         /* File (Always Global) */\r
438         _T("file"), _T("files"), _T("program"), _T("programs"), _T("script"), _T("scripts"),\r
439         _T("document"), _T("documents"), _T("doc"), _T("docs"), _T("header"), _T("headers"),\r
440 \r
441         /*===========================================================*/\r
442         /* Code Topics */\r
443         /* Class (Starts Scope) */\r
444         _T("class"), _T("classes"), _T("structure"), _T("structures"), _T("struct"), _T("structs"),\r
445         _T("package"), _T("packages"), _T("namespace"), _T("namespaces"),\r
446 \r
447         /* Interface (Starts Scope) */\r
448         _T("interface"), _T("interfaces"),\r
449 \r
450         /* Type */\r
451         _T("type"), _T("types"), _T("typedef"), _T("typedefs"),\r
452 \r
453         /* Constant */\r
454         _T("constant"), _T("constants"), _T("const"), _T("consts"),\r
455 \r
456         /* Enumeration (Topic indexed under Types Members indexed under Constants) */\r
457         _T("enumeration"), _T("enumerations"), _T("enum"), _T("enums"),\r
458 \r
459         /* Function (List topics break apart) */\r
460         _T("function"), _T("functions"), _T("func"), _T("funcs"),\r
461         _T("procedure"), _T("procedures"), _T("proc"), _T("procs"),\r
462         _T("routine"), _T("routines"), _T("subroutine"), _T("subroutines"),\r
463         _T("sub"), _T("subs"), _T("method"), _T("methods"),\r
464         _T("callback"), _T("callbacks"), _T("constructor"), _T("constructors"),\r
465         _T("destructor"), _T("destructors"), _T("operator"), _T("operators"),\r
466 \r
467         /* Property */\r
468         _T("property"), _T("properties"), _T("prop"), _T("props"),\r
469 \r
470         /* Event */\r
471         _T("event"), _T("events"),\r
472 \r
473         /* Delegate */\r
474         _T("delegate"), _T("delegates"),\r
475 \r
476         /* Macro */\r
477         _T("macro"), _T("macros"),\r
478         _T("define"), _T("defines"), _T("def"), _T("defs"),\r
479 \r
480         /* Variable */\r
481         _T("variable"), _T("variables"), _T("var"), _T("vars"),\r
482         _T("integer"), _T("integers"), _T("int"), _T("ints"),\r
483         _T("uint"), _T("uints"), _T("long"), _T("longs"),\r
484         _T("ulong"), _T("ulongs"), _T("short"), _T("shorts"),\r
485         _T("ushort"), _T("ushorts"), _T("byte"), _T("bytes"),\r
486         _T("ubyte"), _T("ubytes"), _T("sbyte"), _T("sbytes"),\r
487         _T("float"), _T("floats"), _T("double"), _T("doubles"),\r
488         _T("real"), _T("reals"), _T("decimal"), _T("decimals"),\r
489         _T("scalar"), _T("scalars"), _T("array"), _T("arrays"),\r
490         _T("arrayref"), _T("arrayrefs"), _T("hash"), _T("hashes"),\r
491         _T("hashref"), _T("hashrefs"), _T("bool"), _T("bools"),\r
492         _T("boolean"), _T("booleans"), _T("flag"), _T("flags"),\r
493         _T("bit"), _T("bits"), _T("bitfield"), _T("bitfields"),\r
494         _T("field"), _T("fields"), _T("pointer"), _T("pointers"),\r
495         _T("ptr"), _T("ptrs"), _T("reference"), _T("references"),\r
496         _T("ref"), _T("refs"), _T("object"), _T("objects"),\r
497         _T("obj"), _T("objs"), _T("character"), _T("characters"),\r
498         _T("wcharacter"), _T("wcharacters"), _T("char"), _T("chars"),\r
499         _T("wchar"), _T("wchars"), _T("string"), _T("strings"),\r
500         _T("wstring"), _T("wstrings"), _T("str"), _T("strs"),\r
501         _T("wstr"), _T("wstrs"), _T("handle"), _T("handles"),\r
502 \r
503         /*===========================================================*/\r
504         /* Database Topics */\r
505         /* Database */\r
506         _T("database"), _T("databases"), _T("db"), _T("dbs"),\r
507 \r
508         /* Database Table (Starts Scope) */\r
509         _T("table"), _T("tables"),\r
510         _T("database table"), _T("database tables"), _T("db table"), _T("db tables"),\r
511 \r
512         /* Database View (Starts Scope) */\r
513         _T("view"), _T("views"),\r
514         _T("database view"), _T("database views"), _T("db view"), _T("db views"),\r
515 \r
516         /* Database Cursor */\r
517         _T("cursor"), _T("cursors"),\r
518         _T("database cursor"), _T("database cursors"), _T("db cursor"), _T("db cursors"),\r
519 \r
520         /* Database Index */\r
521         _T("index"), _T("indexes"), _T("indices"),\r
522         _T("database index"), _T("database indexes"), _T("database indices"),\r
523         _T("db index"), _T("db indexes"), _T("db indices"),\r
524         _T("key"), _T("keys"),\r
525         _T("database key"), _T("database keys"), _T("db key"), _T("db keys"),\r
526         _T("primary key"), _T("primary keys"),\r
527         _T("database primary key"), _T("database primary keys"),\r
528         _T("db primary key"), _T("db primary keys"),\r
529 \r
530         /* Database Trigger */\r
531         _T("trigger"), _T("triggers"),\r
532         _T("database trigger"), _T("database triggers"), _T("db trigger"), _T("db triggers"),\r
533 \r
534         /*===========================================================*/\r
535         /* Miscellaneous Topics */\r
536         /* Cookie (Always global) */\r
537         _T("cookie"), _T("cookies"),\r
538 \r
539         /* Build Target */\r
540         _T("target"), _T("targets"),\r
541         _T("build target"), _T("build targets"),\r
542 };\r
543 \r
544 \r
545  \r
546 /***********************************************************************\r
547   <<< [NaturalDocsHeaderClass_initConst] >>> \r
548 ************************************************************************/\r
549 void  NaturalDocsHeaderClass_initConst( NaturalDocsHeaderClass* self )\r
550 {\r
551         self->Keyword = NULL;\r
552         self->Name = NULL;\r
553         self->Brief = NULL;\r
554         Set2_initConst( &self->Arguments );\r
555         self->ReturnValue = NULL;\r
556         self->Descriptions = NULL;\r
557         Set2_initConst( &self->DescriptionItems );\r
558 }\r
559 \r
560 \r
561  \r
562 /***********************************************************************\r
563   <<< [NaturalDocsHeaderClass_finalize] >>> \r
564 ************************************************************************/\r
565 errnum_t  NaturalDocsHeaderClass_finalize( NaturalDocsHeaderClass* self,  errnum_t e )\r
566 {\r
567         Set2_IteratorClass            iterator;\r
568         NaturalDocsDefinitionClass*   p1;\r
569         NaturalDocsDescriptionClass*  p2;\r
570 \r
571 \r
572         e= HeapMemory_free( &self->Keyword, e );\r
573         e= HeapMemory_free( &self->Name, e );\r
574         e= HeapMemory_free( &self->Brief, e );\r
575 \r
576         for ( Set2_forEach2( &self->Arguments, &iterator, &p1 ) ) {\r
577                 e= NaturalDocsDefinitionClass_finalize( p1, e );\r
578         }\r
579         e= Set2_finish( &self->Arguments, e );\r
580 \r
581         e= HeapMemory_free( &self->ReturnValue, e );\r
582         e= HeapMemory_free( &self->Descriptions, e );\r
583 \r
584         for ( Set2_forEach2( &self->DescriptionItems, &iterator, &p2 ) ) {\r
585                 e= NaturalDocsDescriptionClass_finalize( p2, e );\r
586         }\r
587         e= Set2_finish( &self->DescriptionItems, e );\r
588 \r
589         return  e;\r
590 }\r
591 \r
592 \r
593  \r
594 /***********************************************************************\r
595   <<< [NaturalDocsDefinitionClass_initConst] >>> \r
596 ************************************************************************/\r
597 void  NaturalDocsDefinitionClass_initConst( NaturalDocsDefinitionClass* self )\r
598 {\r
599         self->Name = NULL;\r
600         self->Brief = NULL;\r
601 }\r
602 \r
603 \r
604  \r
605 /***********************************************************************\r
606   <<< [NaturalDocsDefinitionClass_finalize] >>> \r
607 ************************************************************************/\r
608 errnum_t  NaturalDocsDefinitionClass_finalize( NaturalDocsDefinitionClass* self,  errnum_t e )\r
609 {\r
610         e= HeapMemory_free( &self->Name, e );\r
611         e= HeapMemory_free( &self->Brief, e );\r
612         return  e;\r
613 }\r
614 \r
615 \r
616  \r
617 /***********************************************************************\r
618   <<< [NaturalDocsDescriptionTypeEnum_to_String] >>> \r
619 ************************************************************************/\r
620 \r
621 static const TCHAR*  gs_NaturalDocsDescriptionTypeEnum_to_String[ NaturalDocsDescriptionType_Count ] = {\r
622         _T("Unknown"), _T("SubTitle"), _T("Paragraph"), _T("Code")\r
623 };\r
624 static_assert_global( NaturalDocsDescriptionType_Unknown   == 0, "" );\r
625 static_assert_global( NaturalDocsDescriptionType_SubTitle  == 1, "" );\r
626 static_assert_global( NaturalDocsDescriptionType_Paragraph == 2, "" );\r
627 static_assert_global( NaturalDocsDescriptionType_Code      == 3, "" );\r
628 \r
629 const TCHAR*  NaturalDocsDescriptionTypeEnum_to_String( int in,  const TCHAR* in_OutOfRange )\r
630 {\r
631         const TCHAR*  ret;\r
632 \r
633         if ( in >= NaturalDocsDescriptionType_Unknown  &&  in < NaturalDocsDescriptionType_Count )\r
634                 { ret = gs_NaturalDocsDescriptionTypeEnum_to_String[ in - NaturalDocsDescriptionType_Unknown ]; }\r
635         else\r
636                 { ret = in_OutOfRange; }\r
637 \r
638         return  ret;\r
639 }\r
640 \r
641 \r
642  \r
643 /***********************************************************************\r
644   <<< [NaturalDocsDescriptionClass_initConst] >>> \r
645 ************************************************************************/\r
646 void  NaturalDocsDescriptionClass_initConst( NaturalDocsDescriptionClass* self )\r
647 {\r
648         self->Type  = NaturalDocsDescriptionType_Unknown;\r
649         self->Start = NULL;\r
650         self->Over  = NULL;\r
651         self->u.Unknown = NULL;\r
652 }\r
653 \r
654 \r
655  \r
656 /***********************************************************************\r
657   <<< [NaturalDocsDescriptionClass_finalize] >>> \r
658 ************************************************************************/\r
659 errnum_t  NaturalDocsDescriptionClass_finalize( NaturalDocsDescriptionClass* self,  errnum_t e )\r
660 {\r
661         if ( self->Type == NaturalDocsDescriptionType_DefinitionList ) {\r
662                 if ( self->u.Definition != NULL )\r
663                         { e= NaturalDocsDefinitionClass_finalize( self->u.Definition, e ); }\r
664                 e= HeapMemory_free( &self->u.Definition, e );\r
665         }\r
666         self->Type = NaturalDocsDescriptionType_Unknown;\r
667 \r
668         return  e;\r
669 }\r
670 \r
671 \r
672  \r
673 /***********************************************************************\r
674   <<< [ParseNaturalDocsComment] >>> \r
675 - HeapMemory_free( out_NaturalDocsHeader );\r
676 ************************************************************************/\r
677 \r
678 void  ParseNaturalDocsLine( const TCHAR*  in_SourceStart,  const TCHAR*  in_SourceOver,\r
679         const TCHAR**  out_LineStart,  const TCHAR**  out_LineOver );\r
680 void  ParseNaturalDocsDefinitionList( const TCHAR*  in_SourceStart,  const TCHAR*  in_SourceOver,\r
681         const TCHAR**  out_NameStart,   const TCHAR**  out_NameOver,\r
682         const TCHAR**  out_BriefStart,  const TCHAR**  out_BriefOver,  bool  in_IsSkipFirstLine );\r
683 \r
684 \r
685 errnum_t  ParseNaturalDocsComment( const TCHAR* in_SourceStart, const TCHAR* in_SourceOver,\r
686         NaturalDocsHeaderClass** out_NaturalDocsHeader,  NaturalDocsParserConfigClass* config )\r
687 {\r
688         errnum_t      e;\r
689         const TCHAR*  p;\r
690         const TCHAR*  p_over;\r
691         int           step_num;\r
692         bool          is_found = false;\r
693         const TCHAR*  descriptions = NULL;\r
694 \r
695         NaturalDocsHeaderClass*       header = NULL;\r
696         NaturalDocsDefinitionClass*   definition_a = NULL;  /* a = for Argument */\r
697         NaturalDocsDefinitionClass*   definition_p = NULL;  /* p = for in Paragraph */\r
698         NaturalDocsDescriptionClass*  description = NULL;\r
699 \r
700         e= HeapMemory_allocate( &header );  IF(e){goto fin;}\r
701         NaturalDocsHeaderClass_initConst( header );\r
702         e= Set2_init( &header->Arguments, 0x10 );  IF(e){goto fin;}\r
703         e= Set2_init( &header->DescriptionItems, 0x40 );  IF(e){goto fin;}\r
704 \r
705 \r
706         /* Parse keyword */\r
707         step_num = 0;\r
708         for ( p = in_SourceStart;  p < in_SourceOver;  p += 1 ) {\r
709                 if ( ! StrT_isCIdentifier( *p ) ) { continue; }\r
710 \r
711                 if ( step_num == 0 ) {\r
712                         p_over = StrT_searchOverOfIdiom( p );\r
713 \r
714                         if ( *p_over != _T(':') ) {\r
715                                 break;  /* This comment is not parsed */\r
716                         }\r
717                         if ( StrT_searchPartStringIndexI( p,  p_over,\r
718                                 g_NaturalDocsKeywords, _countof(g_NaturalDocsKeywords),\r
719                                 NOT_FOUND_INDEX )\r
720                                 == NOT_FOUND_INDEX )\r
721                         {\r
722                                 if ( StrT_searchPartStringIndexI( p,  p_over,\r
723                                         config->AdditionalKeywords, config->AdditionalKeywordsLength,\r
724                                         NOT_FOUND_INDEX )\r
725                                         == NOT_FOUND_INDEX )\r
726                                 {\r
727                                         break;  /* This comment is not parsed */\r
728                                 }\r
729                         }\r
730 \r
731                         e= MallocAndCopyStringByLength( &header->Keyword,  p,  p_over - p );\r
732                                 IF(e){goto fin;}\r
733                         header->KeywordStart = p;\r
734                         header->KeywordOver = p_over;\r
735                         p = p_over;\r
736                 }\r
737                 else if ( step_num == 1 ) {\r
738                         TCHAR*  name = NULL;\r
739 \r
740                         p_over = StrT_chrs( p, _T("\r\n") );\r
741                         ASSERT_R( p_over != NULL,  e=E_OTHERS; goto fin );\r
742                         if ( p_over >= p + 2 ) {\r
743                                 if ( p_over[-2] == _T('*')  &&  p_over[-1] == _T('/') )\r
744                                         { p_over -= 2; }\r
745                         }\r
746                         p_over = StrT_rskip( p, p_over - 1, _T(" \t"), NULL );\r
747                         ASSERT_R( p_over != NULL,  e=E_OTHERS; goto fin );\r
748                         p_over += 1;\r
749 \r
750                         e= MallocAndCopyStringByLength( &name,  p,  p_over - p );\r
751                                 IF(e){goto fin;}\r
752                         e= StrT_trim( name,  sizeof(TCHAR) * ( _tcslen( name ) + 1 ),  name );\r
753                                 IF(e){goto fin;}\r
754                         header->Name = name;\r
755                         header->NameStart = p;\r
756                         header->NameOver = p_over;\r
757                         is_found = true;\r
758                         break;\r
759                 }\r
760                 step_num += 1;\r
761         }\r
762 \r
763         if ( header->Keyword != NULL  &&  header->Name == NULL ) {\r
764                 e= MallocAndCopyString( &header->Name, _T("") );\r
765                         IF(e){goto fin;}\r
766                 is_found = true;\r
767         }\r
768 \r
769 \r
770         /* Parse 2nd line */\r
771         ParseNaturalDocsLine( p,  in_SourceOver,  &p,  &p_over );\r
772         if ( p_over >= in_SourceOver ) {\r
773                 p = in_SourceOver;\r
774         }\r
775         else if ( p == NULL ) {\r
776                 p = p_over;\r
777                 descriptions = p_over;\r
778         }\r
779         else {\r
780                 e= MallocAndCopyStringByLength( &header->Brief,  p,  p_over - p );\r
781                         IF(e){goto fin;}\r
782                 header->BriefStart = p;\r
783                 header->BriefOver = p_over;\r
784 \r
785                 p = StrT_rskip( in_SourceStart,  p - 1,  _T(" \t"), NULL );\r
786                         IF ( p == NULL ) { e=E_OTHERS; goto fin; }\r
787                 header->BriefNoIndent = p + 2;\r
788 \r
789                 p = p_over;\r
790 \r
791                 descriptions = p;\r
792         }\r
793 \r
794 \r
795         /* ... */\r
796         for ( /* p */;  p < in_SourceOver;  p += 1 ) {\r
797                 if ( ! StrT_isCIdentifier( *p ) ) { continue; }\r
798 \r
799                 p_over = StrT_searchOverOfIdiom( p );\r
800 \r
801                 if ( *p_over != _T(':') ) { continue; }\r
802 \r
803                 /* Parse Argument Label */\r
804                 if ( StrT_cmp_i_part( p,  p_over, _T("Arguments") ) == 0 ) {\r
805                         const TCHAR*  p1;\r
806                         const TCHAR*  p1_over;\r
807                         const TCHAR*  p2;\r
808                         const TCHAR*  p2_over;\r
809 \r
810                         header->ArgumentsLabel = p;\r
811 \r
812                         for (;;) {\r
813                                 ParseNaturalDocsDefinitionList( p,  in_SourceOver,\r
814                                         &p1,  &p1_over,  &p2,  &p2_over,  true );\r
815                                 if ( p2 == NULL )\r
816                                         { break; }\r
817 \r
818                                 e= Set2_allocate( &header->Arguments, &definition_a );\r
819                                         IF(e){goto fin;}\r
820                                 NaturalDocsDefinitionClass_initConst( definition_a );\r
821 \r
822                                 e= MallocAndCopyStringByLength( &definition_a->Name,  p1,  p1_over - p1 );\r
823                                         IF(e){goto fin;}\r
824                                 definition_a->NameStart = p1;\r
825                                 definition_a->NameOver = p1_over;\r
826 \r
827                                 e= MallocAndCopyStringByLength( &definition_a->Brief,  p2,  p2_over - p2 );\r
828                                         IF(e){goto fin;}\r
829                                 definition_a->BriefStart = p2;\r
830                                 definition_a->BriefOver = p2_over;\r
831 \r
832                                 definition_a = NULL;\r
833 \r
834                                 descriptions = p2_over;\r
835 \r
836                                 p = p2_over;\r
837                         }\r
838                 }\r
839 \r
840                 /* Parse Return Value Label */\r
841                 else if ( StrT_cmp_i_part( p,  p_over, _T("Return Value") ) == 0 ) {\r
842 \r
843                         header->ReturnValueLabel = p;\r
844 \r
845                         ParseNaturalDocsLine( p,  in_SourceOver,  &p,  &p_over );\r
846                         if ( p == NULL ) {\r
847                                 p = in_SourceOver;\r
848                                 ASSERT_D( p_over != NULL, __noop() );\r
849                         }\r
850                         else {\r
851                                 e= MallocAndCopyStringByLength( &header->ReturnValue,  p,  p_over - p );\r
852                                         IF(e){goto fin;}\r
853                                 header->ReturnValueStart = p;\r
854                                 header->ReturnValueOver = p_over;\r
855 \r
856                                 p = p_over;\r
857                         }\r
858                         descriptions = p_over;\r
859                 }\r
860         }\r
861 \r
862 \r
863         /* Set "header->Descriptions" */\r
864         if ( descriptions != NULL ) {\r
865                 const TCHAR*  descriptions_over;\r
866 \r
867                 descriptions_over = StrT_rstr( in_SourceStart,  in_SourceOver,  _T("\n"),  NULL );\r
868                 if ( descriptions_over != NULL ) {\r
869                         const TCHAR*  over2 = StrT_rstr( in_SourceStart,  descriptions_over - 1,  _T("\n"),  NULL );\r
870                         const TCHAR*  p2;\r
871 \r
872                         /* If last line was only "*******" Then "descriptions_over = over2". */\r
873                         if ( over2 != NULL ) {\r
874                                 p2 = StrT_skip( over2 + 1, _T("* /\t") );\r
875                                         IF ( p2 == NULL ) { e=E_OTHERS; goto fin; }\r
876                                 if ( p2 >= descriptions_over ) {\r
877                                         descriptions_over = over2;\r
878                                 }\r
879                         }\r
880                 }\r
881                 if ( descriptions_over != NULL ) {\r
882                         const TCHAR*  p2;\r
883 \r
884                         if ( *( descriptions_over - 1 ) == _T('\r') )\r
885                                 { descriptions_over -= 1; }\r
886 \r
887                         /* Set "descriptions_over" to before end of comment */\r
888                         p2 = StrT_rskip( descriptions,  descriptions_over - 1,  _T(" \t"),  NULL );\r
889                         if ( p2 != NULL ) {\r
890                                 if ( *p2 == _T('/')  &&  *( p2 - 1 ) == _T('*') ) {\r
891                                         p2 = StrT_rskip( descriptions,  p2 - 2,  _T(" \t"),  NULL );\r
892                                         if ( p2 == NULL ) {\r
893                                                 descriptions_over = descriptions;\r
894                                         } else {\r
895                                                 descriptions_over = p2 + 1;\r
896                                         }\r
897                                 }\r
898                         }\r
899 \r
900                         /* Set "header" */\r
901                         header->DescriptionsStart = descriptions;\r
902                         header->DescriptionsOver = descriptions_over;\r
903                         e= MallocAndCopyStringByLength( &header->Descriptions,\r
904                                 descriptions,  descriptions_over - descriptions );\r
905                                 IF(e){goto fin;}\r
906                 }\r
907         }\r
908 \r
909 \r
910         /* Set "header->DescriptionItems" */\r
911         if ( descriptions != NULL  &&  header->DescriptionsOver != NULL ) {\r
912                 const TCHAR*  line;\r
913                 const TCHAR*  p_last;\r
914                 const TCHAR*  p_line_feed;\r
915                 const TCHAR*  descriptions_over = header->DescriptionsOver;\r
916                 bool          is_definition_list;\r
917 \r
918                 for (\r
919                         line = _tcschr( descriptions, _T('\n') ) + 1;\r
920                         line < descriptions_over;\r
921                         line = p_line_feed + 1 )\r
922                 {\r
923                         p_line_feed = _tcschr( line, _T('\n') );\r
924 \r
925 \r
926                         /* Set "p" : Skip space or "*" */\r
927                         for ( p = line;  p < p_line_feed;  p += 1 ) {\r
928                                 TCHAR  a_char = *p;\r
929 \r
930                                 if ( a_char == ' '  ||  a_char == '\t'  ||  a_char == '*' )\r
931                                         { continue; }\r
932                                 else\r
933                                         { break; }\r
934                         }\r
935 \r
936                         /* Set "p_last" */\r
937                         for ( p_last = p_line_feed - 1;  p_last > p;  p_last -= 1 ) {\r
938                                 TCHAR  a_char = *p_last;\r
939 \r
940                                 if ( a_char == ' '  ||  a_char == '\t'  ||  a_char == '\n' )\r
941                                         { continue; }\r
942                                 else\r
943                                         { break; }\r
944                         }\r
945 \r
946 \r
947                         /* Set "is_definition_list", "definition_p" */\r
948                         {\r
949                                 const TCHAR*  p1;\r
950                                 const TCHAR*  p1_over;\r
951                                 const TCHAR*  p2;\r
952                                 const TCHAR*  p2_over;\r
953 \r
954                                 is_definition_list = false;\r
955                                 p1 = _tcschr( p, _T('-') );\r
956                                 p2 = _tcschr( p, _T('\n') );\r
957 \r
958 \r
959                                 if ( p1 != NULL  &&  p1 < p2 ) {\r
960 \r
961                                         for ( p1_over = p2 - 1;  p1_over > p1;  p1_over -= 1 ) {\r
962                                                 if ( ! _istspace( *p1_over ) )\r
963                                                         { break;}\r
964                                         }\r
965                                         if ( p1_over == p1 ) {\r
966                                                 p1 = NULL;  /* For next if */\r
967                                                 p2_over = NULL;  /* For warning C4701 */\r
968                                         } else {\r
969                                                 ParseNaturalDocsDefinitionList( p,  in_SourceOver,\r
970                                                         &p1,  &p1_over,  &p2,  &p2_over,  false );\r
971                                         }\r
972                                         if ( p1 != NULL  &&  p2 != NULL ) {\r
973                                                 e= HeapMemory_allocate( &definition_p ); IF(e){goto fin;}\r
974                                                 NaturalDocsDefinitionClass_initConst( definition_p );\r
975 \r
976                                                 e= MallocAndCopyStringByLength( &definition_p->Name,\r
977                                                         p1,  p1_over - p1 );\r
978                                                         IF(e){goto fin;}\r
979                                                 definition_p->NameStart = p1;\r
980                                                 definition_p->NameOver = p1_over;\r
981 \r
982                                                 e= MallocAndCopyStringByLength( &definition_p->Brief,\r
983                                                         p2,  p2_over - p2 );\r
984                                                         IF(e){goto fin;}\r
985                                                 definition_p->BriefStart = p2;\r
986                                                 definition_p->BriefOver = p2_over;\r
987                                                 is_definition_list = true;\r
988                                         }\r
989                                 }\r
990                         }\r
991 \r
992 \r
993                         /* End of Paragraph */\r
994                         if ( description != NULL  &&\r
995                                         description->Type == NaturalDocsDescriptionType_Paragraph  &&\r
996                                         p == p_last )\r
997                         {\r
998                                 description = NULL;\r
999                         }\r
1000 \r
1001                         /* End of Code */\r
1002                         if ( description != NULL  &&\r
1003                                         description->Type == NaturalDocsDescriptionType_Code  &&\r
1004                                         *p != _T('>') )\r
1005                         {\r
1006                                 description = NULL;\r
1007                         }\r
1008 \r
1009 \r
1010                         /* Add Code */\r
1011                         if ( *p == _T('>') ) {\r
1012                                 if ( description == NULL  ||\r
1013                                         description->Type != NaturalDocsDescriptionType_Code )\r
1014                                 {\r
1015                                         e= Set2_allocate( &header->DescriptionItems, &description );\r
1016                                                 IF(e){goto fin;}\r
1017                                         NaturalDocsDescriptionClass_initConst( description );\r
1018 \r
1019                                         description->Type = NaturalDocsDescriptionType_Code;\r
1020                                         description->Start = line;\r
1021                                 }\r
1022                                 description->Over = p_line_feed + 1;\r
1023                         }\r
1024 \r
1025                         /* Add SubTitle */\r
1026                         else if ( *p_last == _T(':') ) {\r
1027                                 e= Set2_allocate( &header->DescriptionItems, &description );\r
1028                                         IF(e){goto fin;}\r
1029                                 NaturalDocsDescriptionClass_initConst( description );\r
1030 \r
1031                                 description->Type = NaturalDocsDescriptionType_SubTitle;\r
1032                                 description->Start = p;\r
1033                                 description->Over  = p_last;\r
1034 \r
1035                                 description = NULL;\r
1036                         }\r
1037 \r
1038                         /* Add DefinitionList */\r
1039                         else if ( is_definition_list ) {\r
1040                                 e= Set2_allocate( &header->DescriptionItems, &description );\r
1041                                         IF(e){goto fin;}\r
1042                                 NaturalDocsDescriptionClass_initConst( description );\r
1043 \r
1044                                 description->Type = NaturalDocsDescriptionType_DefinitionList;\r
1045                                 description->Start = line;\r
1046                                 description->Over = p_line_feed + 1;\r
1047                                 description->u.Definition = definition_p;\r
1048 \r
1049                                 description = NULL;\r
1050                                 definition_p = NULL;\r
1051                         }\r
1052 \r
1053                         /* Add Paragraph */\r
1054                         else {\r
1055                                 bool  is_exist_content = false;\r
1056 \r
1057                                 if ( description == NULL  ||\r
1058                                         description->Type != NaturalDocsDescriptionType_Paragraph )\r
1059                                 {\r
1060                                         const TCHAR*  p;\r
1061 \r
1062                                         for ( p = line;  p < p_line_feed;  p += 1 ) {\r
1063                                                 switch ( *p ) {\r
1064                                                         case ' ':  case '\t':  case '*':\r
1065                                                                 break;\r
1066                                                         default:\r
1067                                                                 is_exist_content = true;\r
1068                                                                 goto  exit_for_1;\r
1069                                                 }\r
1070                                         }\r
1071 exit_for_1:;\r
1072                                 }\r
1073                                 if ( is_exist_content ) {\r
1074 \r
1075                                         e= Set2_allocate( &header->DescriptionItems, &description );\r
1076                                                 IF(e){goto fin;}\r
1077                                         NaturalDocsDescriptionClass_initConst( description );\r
1078 \r
1079                                         description->Type = NaturalDocsDescriptionType_Paragraph;\r
1080                                         description->Start = line;\r
1081                                 }\r
1082                                 if ( description != NULL ) {\r
1083                                         description->Over = p_line_feed + 1;\r
1084                                 }\r
1085                         }\r
1086 \r
1087 \r
1088                         /* Delete not used data */\r
1089                         e=0;\r
1090                         if ( definition_p != NULL )\r
1091                                 { e= NaturalDocsDefinitionClass_finalize( definition_p, e ); }\r
1092                         e= HeapMemory_free( &definition_p, e );\r
1093                         IF(e){goto fin;}\r
1094                 }\r
1095         }\r
1096 \r
1097 \r
1098         *out_NaturalDocsHeader = header;\r
1099         header = NULL;\r
1100 \r
1101         e=0;\r
1102 fin:\r
1103         if ( header != NULL ) {\r
1104                 e= Set2_free( &header->Arguments, &definition_a, e );\r
1105                 if ( definition_p != NULL )\r
1106                         { e= NaturalDocsDefinitionClass_finalize( definition_p, e ); }\r
1107                 e= HeapMemory_free( &definition_p, e );\r
1108                 e= Set2_free( &header->DescriptionItems, &description, e );\r
1109         }\r
1110         if ( ! is_found  ||  e != 0 ) {\r
1111                 if ( header == NULL )\r
1112                         { header = *out_NaturalDocsHeader; }\r
1113                 e= NaturalDocsHeaderClass_finalize( header, e );\r
1114                 e= HeapMemory_free( &header, e );\r
1115                 *out_NaturalDocsHeader = NULL;\r
1116         }\r
1117         return  e;\r
1118 }\r
1119 \r
1120 \r
1121  \r
1122 /***********************************************************************\r
1123   <<< [ParseNaturalDocsLine] >>> \r
1124 ************************************************************************/\r
1125 void  ParseNaturalDocsLine( const TCHAR*  in_SourceStart,  const TCHAR*  in_SourceOver,\r
1126         const TCHAR**  out_LineStart,  const TCHAR**  out_LineOver )\r
1127 {\r
1128         const TCHAR*  p;\r
1129         const TCHAR*  p_over;  /* position of over */\r
1130         TCHAR         a_char;  /* char = charcter */\r
1131 \r
1132 \r
1133         *out_LineStart = NULL;\r
1134         *out_LineOver  = NULL;\r
1135 \r
1136 \r
1137         /* Move to next line */\r
1138         for ( p = in_SourceStart;  p < in_SourceOver;  p += 1 ) {\r
1139                 if ( *p == '\n' ) {\r
1140                         p += 1;\r
1141                         break;\r
1142                 }\r
1143         }\r
1144 \r
1145         /* Skip space or "*" */\r
1146         for ( /* p */ ;  p < in_SourceOver;  p += 1 ) {\r
1147                 a_char = *p;\r
1148 \r
1149                 if ( a_char == ' '  ||  a_char == '\t'  ||  a_char == '*' )\r
1150                         { continue; }\r
1151                 else\r
1152                         { break; }\r
1153         }\r
1154 \r
1155         /* Move to right of line */\r
1156         for ( p_over = p;  p_over < in_SourceOver;  p_over += 1 ) {\r
1157                 a_char = *p_over;\r
1158 \r
1159                 if ( a_char == '\n' ) {\r
1160                         for ( p_over -= 1;  /* p_over >= p */;  p_over -= 1 ) {\r
1161                                 if ( p_over <= p ) {\r
1162                                         p_over = p;\r
1163                                         break;\r
1164                                 }\r
1165 \r
1166                                 a_char = *p_over;\r
1167 \r
1168                                 if ( a_char == ' '  ||  a_char == '\t' ) {\r
1169                                         continue;\r
1170                                 } else {\r
1171                                         p_over += 1;\r
1172                                         break;\r
1173                                 }\r
1174                         }\r
1175 \r
1176                         if ( p != p_over ) {\r
1177                                 *out_LineStart = p;\r
1178                         }\r
1179                         break;\r
1180                 }\r
1181         }\r
1182         *out_LineOver = p_over;\r
1183 \r
1184         if ( p_over > p + 2  &&  *( p_over - 2 ) == _T('*')  &&  *( p_over - 1 ) == _T('/')  &&  *out_LineStart == NULL ) {\r
1185                 for ( p_over -= 3;  p_over > p;  p_over -= 1 ) {\r
1186                         a_char = *p_over;\r
1187 \r
1188                         if ( a_char == ' '  ||  a_char == '\t' )\r
1189                                 { continue; }\r
1190                         else\r
1191                                 { break; }\r
1192                 }\r
1193                 \r
1194                 *out_LineStart = p;\r
1195                 *out_LineOver = p_over + 1;\r
1196         }\r
1197 }\r
1198 \r
1199 \r
1200  \r
1201 /***********************************************************************\r
1202   <<< [ParseNaturalDocsDefinitionList] >>> \r
1203 ************************************************************************/\r
1204 void  ParseNaturalDocsDefinitionList( const TCHAR*  in_SourceStart,  const TCHAR*  in_SourceOver,\r
1205         const TCHAR**  out_NameStart,   const TCHAR**  out_NameOver,\r
1206         const TCHAR**  out_BriefStart,  const TCHAR**  out_BriefOver,  bool  in_IsSkipFirstLine )\r
1207 {\r
1208         const TCHAR*  p;\r
1209         const TCHAR*  p_over;\r
1210         TCHAR         a_char;  /* char = charcter */\r
1211 \r
1212 \r
1213         *out_NameStart = NULL;\r
1214         *out_BriefStart = NULL;\r
1215 \r
1216         if ( in_IsSkipFirstLine ) {\r
1217                 for ( p = in_SourceStart;  p < in_SourceOver;  p += 1 ) {\r
1218                         if ( *p == '\n' ) {\r
1219                                 p += 1;\r
1220                                 break;\r
1221                         }\r
1222                 }\r
1223         }\r
1224         else {\r
1225                 p = in_SourceStart;\r
1226         }\r
1227 \r
1228         for ( /* p */ ;  p < in_SourceOver;  p += 1 ) {\r
1229                 a_char = *p;\r
1230 \r
1231                 if ( a_char == ' '  ||  a_char == '\t'  ||  a_char == '*' )\r
1232                         { continue; }\r
1233                 else\r
1234                         { break; }\r
1235         }\r
1236         for ( p_over = p;  p_over < in_SourceOver;  p_over += 1 ) {\r
1237                 a_char = *p_over;\r
1238 \r
1239                 if ( a_char == '-' ) {\r
1240                         if ( p_over == p ) {\r
1241                                 break;  /* Not definition list but normal list */\r
1242                         }\r
1243                         else {\r
1244                                 const TCHAR*  p2_over;\r
1245 \r
1246                                 for ( p2_over = p_over - 1;  /* p2_over >= p */;  p2_over -= 1 ) {\r
1247                                         a_char = *p2_over;\r
1248                                         if ( a_char == ' '  ||  a_char == '\t' ) {\r
1249                                                 continue;\r
1250                                         } else {\r
1251                                                 p2_over += 1;\r
1252                                                 break;\r
1253                                         }\r
1254                                 }\r
1255 \r
1256                                 *out_NameStart = p;\r
1257                                 *out_NameOver = p2_over;\r
1258                         }\r
1259                         break;\r
1260                 }\r
1261                 else if ( a_char == '\n' ) {\r
1262                         goto fin;\r
1263                 }\r
1264         }\r
1265         for ( p = p_over + 1;  p < in_SourceOver;  p += 1 ) {\r
1266                 a_char = *p;\r
1267 \r
1268                 if ( a_char == ' '  ||  a_char == '\t'  ||  a_char == '*' )\r
1269                         { continue; }\r
1270                 else\r
1271                         { break; }\r
1272         }\r
1273         for ( p_over = p;  p_over < in_SourceOver;  p_over += 1 ) {\r
1274                 a_char = *p_over;\r
1275 \r
1276                 if ( a_char == '\n' ) {\r
1277                         for ( p_over -= 1;  /* p_over >= p */;  p_over -= 1 ) {\r
1278                                 a_char = *p_over;\r
1279                                 if ( a_char == ' '  ||  a_char == '\t' ) {\r
1280                                         continue;\r
1281                                 } else {\r
1282                                         p_over += 1;\r
1283                                         break;\r
1284                                 }\r
1285                         }\r
1286 \r
1287                         *out_BriefStart = p;\r
1288                         *out_BriefOver = p_over;\r
1289                         break;\r
1290                 }\r
1291         }\r
1292 \r
1293 fin:\r
1294         return;\r
1295 }\r
1296 \r
1297 \r
1298  \r
1299 /***********************************************************************\r
1300   <<< (NaturalCommentClass) >>> \r
1301 ************************************************************************/\r
1302 \r
1303 static const FinalizerVTableClass  gs_NaturalCommentClass_FinalizerVTable = {\r
1304         offsetof( NaturalCommentClass, FinalizerVTable ),\r
1305         NaturalCommentClass_finalize,\r
1306 };\r
1307 static const PrintXML_VTableClass  gs_NaturalCommentClass_PrintXML_VTable = {\r
1308         offsetof( NaturalCommentClass, PrintXML_VTable ),\r
1309         NaturalCommentClass_printXML,\r
1310 };\r
1311 static const InterfaceToVTableClass  gs_NaturalCommentClass_InterfaceToVTables[] = {\r
1312         { &g_FinalizerInterface_ID, &gs_NaturalCommentClass_FinalizerVTable },\r
1313         { &g_PrintXML_Interface_ID, &gs_NaturalCommentClass_PrintXML_VTable },\r
1314 };\r
1315 static const ClassID_Class*  gs_NaturalCommentClass_SuperClassIDs[] = {\r
1316         &g_ClassID_SuperClass_ID, &g_ParsedRangeClass_ID, &g_SyntaxSubNodeClass_ID,\r
1317         &g_SyntaxNodeClass_ID, &g_NaturalCommentClass_ID,\r
1318 };\r
1319 \r
1320 /*[g_NaturalCommentClass_ID]*/\r
1321 const ClassID_Class  g_NaturalCommentClass_ID = {\r
1322         "NaturalCommentClass",\r
1323         gs_NaturalCommentClass_SuperClassIDs,\r
1324         _countof( gs_NaturalCommentClass_SuperClassIDs ),\r
1325         sizeof( NaturalCommentClass ),\r
1326         NULL,\r
1327         gs_NaturalCommentClass_InterfaceToVTables,\r
1328         _countof( gs_NaturalCommentClass_InterfaceToVTables ),\r
1329 };\r
1330 \r
1331 \r
1332  \r
1333 /***********************************************************************\r
1334   <<< [NaturalCommentClass_initConst] >>> \r
1335 ************************************************************************/\r
1336 void  NaturalCommentClass_initConst( NaturalCommentClass* self )\r
1337 {\r
1338         SyntaxNodeClass_initConst( (SyntaxNodeClass*) self );\r
1339         self->ClassID = &g_NaturalCommentClass_ID;\r
1340         self->FinalizerVTable = &gs_NaturalCommentClass_FinalizerVTable;\r
1341         self->PrintXML_VTable = &gs_NaturalCommentClass_PrintXML_VTable;\r
1342         self->NaturalDocsHeader = NULL;\r
1343 }\r
1344 \r
1345 \r
1346  \r
1347 /***********************************************************************\r
1348   <<< [NaturalCommentClass_finalize] >>> \r
1349 ************************************************************************/\r
1350 errnum_t  NaturalCommentClass_finalize( NaturalCommentClass* self, errnum_t e )\r
1351 {\r
1352         if ( self->NaturalDocsHeader != NULL ) {\r
1353                 e= NaturalDocsHeaderClass_finalize( self->NaturalDocsHeader, e );\r
1354                 e= HeapMemory_free( &self->NaturalDocsHeader, e );\r
1355         }\r
1356         return  e;\r
1357 }\r
1358 \r
1359 \r
1360  \r
1361 /***********************************************************************\r
1362   <<< [NaturalCommentClass_printXML] >>> \r
1363 ************************************************************************/\r
1364 errnum_t  NaturalCommentClass_printXML( NaturalCommentClass* self, FILE* OutputStream )\r
1365 {\r
1366         errnum_t     e;\r
1367         int          r;\r
1368         Set2_IteratorClass           iterator;\r
1369         NaturalDocsHeaderClass*      header;\r
1370         NaturalDocsDefinitionClass*  definition;\r
1371         NaturalDocsDescriptionClass* description;\r
1372 \r
1373 \r
1374         r= _ftprintf_s( OutputStream, _T("<NaturalCommentClass") );\r
1375                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1376 \r
1377         header = self->NaturalDocsHeader;\r
1378         if ( header != NULL ) {\r
1379                 r= _ftprintf_s( OutputStream, _T("  NaturalDocsKeyword=\"%s\""), header->Keyword );\r
1380                         IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1381 \r
1382                 ASSERT_D( StrT_cmp_part( header->KeywordStart,  header->KeywordOver,  header->Keyword ) == 0,\r
1383                         e=E_OTHERS; goto fin );\r
1384 \r
1385 \r
1386                 r= _ftprintf_s( OutputStream, _T("  Name=\"%s\""), header->Name );\r
1387                         IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1388 \r
1389                 ASSERT_D( StrT_cmp_part( header->NameStart,  header->NameOver,  header->Name ) == 0,\r
1390                         e=E_OTHERS; goto fin );\r
1391         }\r
1392         r= _ftprintf_s( OutputStream, _T("  StartLineNum=\"%d\""), self->StartLineNum );\r
1393                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1394 \r
1395         r= _ftprintf_s( OutputStream, _T("  LastLineNum=\"%d\""), self->LastLineNum );\r
1396                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1397 \r
1398         if ( self->ParentComment != NULL ) {\r
1399                 r= _ftprintf_s( OutputStream, _T("  ParentComment=\"%s\""), self->ParentComment->NaturalDocsHeader->Name );\r
1400                         IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1401         }\r
1402         r= _ftprintf_s( OutputStream, _T(">\n") );\r
1403                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1404 \r
1405 \r
1406         if ( header != NULL ) {\r
1407                 if ( header->Brief != NULL ) {\r
1408                         r= _ftprintf_s( OutputStream, _T("\t<Brief><![CDATA[%s]]></Brief>\n"), header->Brief );\r
1409                                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1410 \r
1411                         ASSERT_D( StrT_cmp_part( header->BriefStart,  header->BriefOver,  header->Brief ) == 0,\r
1412                                 e=E_OTHERS; goto fin );\r
1413                         ASSERT_D( header->BriefNoIndent > header->NameOver  &&\r
1414                                 header->BriefNoIndent < header->BriefStart,\r
1415                                 e=E_OTHERS; goto fin );\r
1416                 }\r
1417 \r
1418                 if ( header->Arguments.First < header->Arguments.Next ) {\r
1419                         ASSERT_D( StrT_cmp_part( header->ArgumentsLabel,  header->ArgumentsLabel + 10,\r
1420                                 _T("Arguments:") ) == 0,  e=E_OTHERS; goto fin );\r
1421                 }\r
1422                 for ( Set2_forEach2( &header->Arguments, &iterator, &definition ) ) {\r
1423                         r= _ftprintf_s( OutputStream, _T("\t<Arguments  Name=\"%s\"><![CDATA[%s]]></Arguments>\n"),\r
1424                                 definition->Name,  definition->Brief );\r
1425                                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1426 \r
1427                         ASSERT_D( StrT_cmp_part( definition->NameStart,  definition->NameOver,  definition->Name )\r
1428                                 == 0,  e=E_OTHERS; goto fin );\r
1429                         ASSERT_D( StrT_cmp_part( definition->BriefStart,  definition->BriefOver,  definition->Brief )\r
1430                                 == 0,  e=E_OTHERS; goto fin );\r
1431                 }\r
1432 \r
1433                 if ( header->ReturnValue != NULL ) {\r
1434                         r= _ftprintf_s( OutputStream, _T("\t<ReturnValue><![CDATA[%s]]></ReturnValue>\n"), header->ReturnValue );\r
1435                                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1436 \r
1437                         ASSERT_D( StrT_cmp_part( header->ReturnValueStart,  header->ReturnValueOver,\r
1438                                 header->ReturnValue ) == 0,  e=E_OTHERS; goto fin );\r
1439                         ASSERT_D( StrT_cmp_part( header->ReturnValueLabel,  header->ReturnValueLabel + 13,\r
1440                                 _T("Return Value:") ) == 0,  e=E_OTHERS; goto fin );\r
1441                 }\r
1442 \r
1443                 if ( ! Set2_isEmpty( &header->DescriptionItems ) ) {\r
1444                         r= _ftprintf_s( OutputStream, _T("\t<DescriptionItems>\n") );\r
1445                                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1446                 }\r
1447                 for ( Set2_forEach2( &header->DescriptionItems, &iterator, &description ) ) {\r
1448                         r= _ftprintf_s( OutputStream, _T("\t\t<DescriptionItem  type=\"%s\"><![CDATA["),\r
1449                                 NaturalDocsDescriptionTypeEnum_to_String( description->Type, _T("UNKNOWN") ) );\r
1450                                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1451                         e= ftcopy_part_r( OutputStream, description->Start, description->Over );\r
1452                         r= _ftprintf_s( OutputStream, _T("]]></DescriptionItem>\n") );\r
1453                                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1454                 }\r
1455                 if ( ! Set2_isEmpty( &header->DescriptionItems ) ) {\r
1456                         r= _ftprintf_s( OutputStream, _T("\t</DescriptionItems>\n") );\r
1457                                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1458                 }\r
1459         }\r
1460 \r
1461 \r
1462         r= _ftprintf_s( OutputStream, _T("</NaturalCommentClass>\n") );\r
1463                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
1464 \r
1465         e=0;\r
1466 fin:\r
1467         return  e;\r
1468 }\r
1469 \r
1470 \r
1471  \r
1472 /***********************************************************************\r
1473   <<< [MakeNaturalComments_C_Language] >>> \r
1474 ************************************************************************/\r
1475 \r
1476 errnum_t  MakeNaturalComments_C_Language__Sub( C_LanguageTokenClass* StartToken,\r
1477         LineNumberIndexClass*  LineNumbers,\r
1478         NaturalCommentClass** out_NewComment,\r
1479         NaturalDocsParserConfigClass* config );\r
1480 \r
1481 errnum_t  MakeNaturalComments_C_Language( ListClass* /*<C_LanguageTokenClass*>*/ TokenList,\r
1482         LineNumberIndexClass*  LineNumbers,\r
1483         ListClass* /*<NaturalCommentClass*>*/ TopSyntaxNodeList,\r
1484         NaturalDocsParserConfigClass* config )\r
1485 {\r
1486         errnum_t                      e;\r
1487         const ClassID_Class*          class_ID;\r
1488         ListIteratorClass             iterator;\r
1489         C_LanguageTokenClass*         token;\r
1490         NaturalCommentClass*          comment;\r
1491         NaturalCommentClass*          new_comment;\r
1492         NaturalDocsParserConfigClass  config_body;\r
1493 \r
1494 \r
1495         if ( config == NULL ) {\r
1496                 config = &config_body;\r
1497                 config->Flags = 0;\r
1498         }\r
1499 \r
1500         if ( IsBitNotSet( config->Flags, NaturalDocsParserConfig_AdditionalKeywords ) ) {\r
1501                 config->AdditionalKeywords       = NULL;\r
1502                 config->AdditionalKeywordsLength = 0;\r
1503         }\r
1504         else {\r
1505                 ASSERT_R( IsBitSet( config->Flags, NaturalDocsParserConfig_AdditionalKeywordsLength ),\r
1506                         e=E_OTHERS; goto fin );\r
1507         }\r
1508 \r
1509         if ( IsBitSet( config->Flags, NaturalDocsParserConfig_AdditionalKeywordsEndsScopesFirstIndex ) ) {\r
1510                 if ( IsBitNotSet( config->Flags, NaturalDocsParserConfig_AdditionalKeywordsEndsScopesLength ) ) {\r
1511                         config->AdditionalKeywordsEndsScopesLength = 1;\r
1512                 }\r
1513         }\r
1514         else {\r
1515                 config->AdditionalKeywordsEndsScopesFirstIndex = 0;\r
1516                 config->AdditionalKeywordsEndsScopesLength = 0;\r
1517         }\r
1518 \r
1519 \r
1520         for ( ListClass_forEach( TokenList, &iterator, &token ) ) {\r
1521                 class_ID = token->ClassID;\r
1522                 if ( class_ID == &g_C_LanguageTokenClass_ID ) {\r
1523                         C_LanguageTokenEnum    token_type = token->TokenType;\r
1524 \r
1525                         if ( token_type == TwoChar8( '/', '*' ) ) {\r
1526                                 e= MakeNaturalComments_C_Language__Sub( token, LineNumbers, &new_comment, config );\r
1527                                         IF(e){goto fin;}\r
1528                                 if ( new_comment != NULL ) {\r
1529                                         e= ListClass_addLast( TopSyntaxNodeList, &new_comment->ListElement );\r
1530                                                 IF(e){goto fin;}\r
1531                                 }\r
1532                         }\r
1533                 }\r
1534         }\r
1535 \r
1536         /* Set "comment->ParentComment" */\r
1537         {\r
1538                 enum {\r
1539                         starts_scope_start = 19,\r
1540                         starts_scope_end   = 30,\r
1541                         ends_scope_start   = 4, \r
1542                         ends_scope_end     = 5,\r
1543                 };\r
1544 \r
1545                 NaturalCommentClass*  parent = NULL;\r
1546 \r
1547 \r
1548                 ASSERT_D( _tcscmp( g_NaturalDocsKeywords[ starts_scope_start ], _T("class")      ) == 0,  e=E_OTHERS; goto fin );\r
1549                 ASSERT_D( _tcscmp( g_NaturalDocsKeywords[ starts_scope_end ],   _T("interfaces") ) == 0,  e=E_OTHERS; goto fin );\r
1550                 ASSERT_D( _tcscmp( g_NaturalDocsKeywords[ ends_scope_start ],   _T("section")    ) == 0,  e=E_OTHERS; goto fin );\r
1551                 ASSERT_D( _tcscmp( g_NaturalDocsKeywords[ ends_scope_end ],     _T("title")      ) == 0,  e=E_OTHERS; goto fin );\r
1552 \r
1553 \r
1554                 for ( ListClass_forEach( TopSyntaxNodeList, &iterator, &comment ) ) {\r
1555                         NaturalDocsHeaderClass*  header = comment->NaturalDocsHeader;\r
1556                         int  index;\r
1557 \r
1558                         index = StrT_searchPartStringIndexI( header->KeywordStart,  header->KeywordOver,\r
1559                                 g_NaturalDocsKeywords, _countof(g_NaturalDocsKeywords),\r
1560                                 NOT_FOUND_INDEX );\r
1561 \r
1562                         if ( index == NOT_FOUND_INDEX ) {\r
1563                                 index = StrT_searchPartStringIndexI( header->KeywordStart,  header->KeywordOver,\r
1564                                         config->AdditionalKeywords, config->AdditionalKeywordsLength,\r
1565                                         NOT_FOUND_INDEX );\r
1566 \r
1567                                 if ( index >= config->AdditionalKeywordsEndsScopesFirstIndex  &&\r
1568                                         index < config->AdditionalKeywordsEndsScopesFirstIndex +\r
1569                                         config->AdditionalKeywordsEndsScopesLength )\r
1570                                 {\r
1571                                         index = ends_scope_start;\r
1572                                 }\r
1573                                 else {\r
1574                                         index = NOT_FOUND_INDEX;\r
1575                                 }\r
1576                         }\r
1577 \r
1578                         if ( index >= starts_scope_start  &&  index <= starts_scope_end ) {\r
1579                                 parent = comment;\r
1580                                 comment->ParentComment = NULL;\r
1581                         }\r
1582                         else if ( index >= ends_scope_start  &&  index <= ends_scope_end ) {\r
1583                                 parent = NULL;\r
1584                                 comment->ParentComment = NULL;\r
1585                         }\r
1586                         else {\r
1587                                 comment->ParentComment = parent;\r
1588                         }\r
1589                 }\r
1590         }\r
1591 \r
1592         e=0;\r
1593 fin:\r
1594         return  e;\r
1595 }\r
1596 \r
1597 \r
1598 errnum_t  MakeNaturalComments_C_Language__Sub( C_LanguageTokenClass* StartToken,\r
1599         LineNumberIndexClass*  LineNumbers,\r
1600         NaturalCommentClass** out_NewComment,\r
1601         NaturalDocsParserConfigClass* config )\r
1602 {\r
1603         errnum_t                e;\r
1604         C_LanguageTokenClass*   token;\r
1605         NaturalCommentClass*    new_comment;\r
1606         int                     line_num;\r
1607 \r
1608         *out_NewComment = NULL;\r
1609 \r
1610         e= HeapMemory_allocate( &new_comment ); IF(e){goto fin;}\r
1611         NaturalCommentClass_initConst( new_comment );\r
1612 \r
1613 \r
1614         /* Set members of "new_comment" */\r
1615         new_comment->Start = StartToken->Start;\r
1616         e= LineNumberIndexClass_searchLineNumber( LineNumbers, new_comment->Start, &line_num );\r
1617                 IF(e){goto fin;}\r
1618         new_comment->StartLineNum = line_num;\r
1619 \r
1620 \r
1621         token = StartToken;\r
1622         for (;;) {\r
1623                 token = (C_LanguageTokenClass*) token->ListElement.Next->Data;\r
1624                         IF ( token == NULL ) { e=E_OTHERS; goto fin; }\r
1625                 if ( token->TokenType == TwoChar8( '*', '/' ) )\r
1626                         { break; }\r
1627         }\r
1628 \r
1629         new_comment->Over = token->Over;\r
1630         e= LineNumberIndexClass_searchLineNumber( LineNumbers, new_comment->Over - 1, &line_num );\r
1631                 IF(e){goto fin;}\r
1632         new_comment->LastLineNum = line_num;\r
1633 \r
1634 \r
1635         /* ... */\r
1636         e= ParseNaturalDocsComment( new_comment->Start, new_comment->Over,\r
1637                 &new_comment->NaturalDocsHeader, config ); IF(e){goto fin;}\r
1638 \r
1639 \r
1640         /* Set "*out_NewComment" */\r
1641         if ( new_comment->NaturalDocsHeader != NULL ) {\r
1642                 *out_NewComment = new_comment;\r
1643                 new_comment = NULL;\r
1644         }\r
1645         e=0;\r
1646 fin:\r
1647         if ( new_comment != NULL ) {\r
1648                 e= NaturalCommentClass_finalize( new_comment, e );\r
1649                 HeapMemory_free( &new_comment, e );\r
1650         }\r
1651 \r
1652         return  e;\r
1653 }\r
1654 \r
1655 \r
1656  \r
1657 /***********************************************************************\r
1658   <<< [LexicalAnalize_C_Language] >>> \r
1659 ************************************************************************/\r
1660 errnum_t  LexicalAnalize_C_Language( const TCHAR*  in_Text,\r
1661         ListClass* /*<C_LanguageTokenClass>*/  in_TokenList )\r
1662 {\r
1663         errnum_t      e;\r
1664         const TCHAR*  p;\r
1665         TCHAR         c;\r
1666         TCHAR         c2;\r
1667         int           next_plus;\r
1668         bool          is_in_c_comment = false;    /* Slash asterisk */\r
1669         bool          is_in_cpp_comment = false;  /* Double slash */\r
1670 \r
1671         C_LanguageTokenEnum     token_type;\r
1672         C_LanguageTokenClass*   token = NULL;\r
1673 \r
1674 \r
1675         p = in_Text;\r
1676         c = *p;\r
1677         while ( c != '\0' ) {\r
1678                 next_plus = 1;\r
1679 \r
1680                 if      ( c >= 'A'  &&  c <= 'Z' ) { token_type = gc_TokenOfCIdentifier; }\r
1681                 else if ( c >= 'a'  &&  c <= 'z' ) { token_type = gc_TokenOfCIdentifier; }\r
1682                 else if ( c == '_' )               { token_type = gc_TokenOfCIdentifier; }\r
1683                 else if ( c >= '0'  &&  c <= '9' ) { token_type = gc_TokenOfNumber; }\r
1684                 else if ( c == '=' ) {\r
1685                         c2 = *( p + 1 );\r
1686                         if      ( c2 == '=' ) { token_type = TwoChar8( '=', '=' );  next_plus = 2; }\r
1687                         else                  { token_type = '='; }\r
1688                 }\r
1689                 else if ( c == '+' ) {\r
1690                         c2 = *( p + 1 );\r
1691                         if      ( c2 == '+' ) { token_type = TwoChar8( '+', '+' );  next_plus = 2; }\r
1692                         else if ( c2 == '=' ) { token_type = TwoChar8( '+', '=' );  next_plus = 2; }\r
1693                         else                  { token_type = '+'; }\r
1694                 }\r
1695                 else if ( c == '-' ) {\r
1696                         c2 = *( p + 1 );\r
1697                         if      ( c2 == '>' ) { token_type = TwoChar8( '-', '>' );  next_plus = 2; }\r
1698                         else if ( c2 == '-' ) { token_type = TwoChar8( '-', '-' );  next_plus = 2; }\r
1699                         else if ( c2 == '=' ) { token_type = TwoChar8( '-', '=' );  next_plus = 2; }\r
1700                         else                  { token_type = '-'; }\r
1701                 }\r
1702                 else if ( c == '*' ) {\r
1703                         c2 = *( p + 1 );\r
1704                         if      ( c2 == '/' ) { token_type = TwoChar8( '*', '/' );  next_plus = 2; }\r
1705                         else if ( c2 == '=' ) { token_type = TwoChar8( '*', '=' );  next_plus = 2; }\r
1706                         else                  { token_type = '*'; }\r
1707 \r
1708                         if ( c2 == '/' ) {\r
1709                                 if ( ! is_in_cpp_comment )\r
1710                                         { is_in_c_comment = false; }\r
1711                         }\r
1712                 }\r
1713                 else if ( c == '/' ) {\r
1714                         c2 = *( p + 1 );\r
1715                         if      ( c2 == '/' ) { token_type = TwoChar8( '/', '/' );  next_plus = 2; }\r
1716                         else if ( c2 == '*' ) { token_type = TwoChar8( '/', '*' );  next_plus = 2; }\r
1717                         else if ( c2 == '=' ) { token_type = TwoChar8( '/', '=' );  next_plus = 2; }\r
1718                         else                  { token_type = '/'; }\r
1719 \r
1720                         if ( ! is_in_c_comment  &&  ! is_in_cpp_comment ) {\r
1721                                 if ( c2 == '/' )\r
1722                                         { is_in_cpp_comment = true; }\r
1723                                 else if ( c2 == '*' )\r
1724                                         { is_in_c_comment = true; }\r
1725                         }\r
1726                 }\r
1727                 else if ( c == '<' ) {\r
1728                         c2 = *( p + 1 );\r
1729                         if      ( c2 == '<' ) { token_type = TwoChar8( '<', '<' );  next_plus = 2; }\r
1730                         else if ( c2 == '=' ) { token_type = TwoChar8( '<', '=' );  next_plus = 2; }\r
1731                         else                  { token_type = '<'; }\r
1732                 }\r
1733                 else if ( c == '>' ) {\r
1734                         c2 = *( p + 1 );\r
1735                         if      ( c2 == '>' ) { token_type = TwoChar8( '>', '>' );  next_plus = 2; }\r
1736                         else if ( c2 == '=' ) { token_type = TwoChar8( '>', '=' );  next_plus = 2; }\r
1737                         else                  { token_type = '>'; }\r
1738                 }\r
1739                 else if ( c == '!' ) {\r
1740                         c2 = *( p + 1 );\r
1741                         if      ( c2 == '=' ) { token_type = TwoChar8( '!', '=' );  next_plus = 2; }\r
1742                         else                  { token_type = '!'; }\r
1743                 }\r
1744                 else if ( c == '&' ) {\r
1745                         c2 = *( p + 1 );\r
1746                         if      ( c2 == '&' ) { token_type = TwoChar8( '&', '&' );  next_plus = 2; }\r
1747                         else if ( c2 == '=' ) { token_type = TwoChar8( '&', '=' );  next_plus = 2; }\r
1748                         else                  { token_type = '&'; }\r
1749                 }\r
1750                 else if ( c == '|' ) {\r
1751                         c2 = *( p + 1 );\r
1752                         if      ( c2 == '|' ) { token_type = TwoChar8( '|', '|' );  next_plus = 2; }\r
1753                         else if ( c2 == '=' ) { token_type = TwoChar8( '|', '=' );  next_plus = 2; }\r
1754                         else                  { token_type = '|'; }\r
1755                 }\r
1756                 else if ( c == '%' ) {\r
1757                         c2 = *( p + 1 );\r
1758                         if      ( c2 == '=' ) { token_type = TwoChar8( '%', '=' );  next_plus = 2; }\r
1759                         else                  { token_type = '%'; }\r
1760                 }\r
1761                 else if ( c == '^' ) {\r
1762                         c2 = *( p + 1 );\r
1763                         if      ( c2 == '=' ) { token_type = TwoChar8( '^', '=' );  next_plus = 2; }\r
1764                         else                  { token_type = '^'; }\r
1765                 }\r
1766                 else {\r
1767                         switch ( c ) {\r
1768                                 case  '(':  token_type = c;  break;\r
1769                                 case  ')':  token_type = c;  break;\r
1770                                 case  '{':  token_type = c;  break;\r
1771                                 case  '}':  token_type = c;  break;\r
1772                                 case  '[':  token_type = c;  break;\r
1773                                 case  ']':  token_type = c;  break;\r
1774                                 case  '"':  token_type = gc_TokenOfString;  break;\r
1775                                 case  '\'': token_type = gc_TokenOfChar;  break;\r
1776                                 case  '.':  token_type = c;  break;\r
1777                                 case  ',':  token_type = c;  break;\r
1778                                 case  ':':  token_type = c;  break;\r
1779                                 case  ';':  token_type = c;  break;\r
1780                                 case  '\n': token_type = c;  is_in_cpp_comment = false;  break;\r
1781                                 case  '?':  token_type = c;  break;\r
1782                                 case  '~':  token_type = c;  break;\r
1783                                 default:    token_type = gc_TokenOfOther;  break;\r
1784                         }\r
1785                 }\r
1786 \r
1787                 if ( token_type == gc_TokenOfCIdentifier ) {\r
1788                         bool  is_in_identifier;\r
1789 \r
1790                         for (;;) {\r
1791                                 c2 = *( p + next_plus );\r
1792                                 if      ( c2 >= 'A'  &&  c2 <= 'Z' ) { is_in_identifier = true; }\r
1793                                 else if ( c2 >= 'a'  &&  c2 <= 'z' ) { is_in_identifier = true; }\r
1794                                 else if ( c2 >= '0'  &&  c2 <= '9' ) { is_in_identifier = true; }\r
1795                                 else if ( c2 == '_' )                { is_in_identifier = true; }\r
1796                                 else                                 { is_in_identifier = false; }\r
1797 \r
1798                                 if ( ! is_in_identifier )\r
1799                                         { break; }\r
1800 \r
1801                                 next_plus += 1;\r
1802                         }\r
1803                 }\r
1804                 else if ( ( token_type == gc_TokenOfString  ||  token_type == gc_TokenOfChar ) &&\r
1805                                 ( ! is_in_c_comment  &&  ! is_in_cpp_comment ) )\r
1806                 {\r
1807                         bool  is_escape = false;\r
1808 \r
1809                         for (;;) {\r
1810                                 c2 = *( p + next_plus );\r
1811                                 if ( ! is_escape ) {\r
1812                                         if ( c2 == c ) {\r
1813                                                 next_plus += 1;\r
1814                                                 break;\r
1815                                         }\r
1816                                         else if ( c2 == '\\' ) {\r
1817                                                 is_escape = true;\r
1818                                         }\r
1819                                 }\r
1820                                 else {\r
1821                                         is_escape = false;\r
1822                                 }\r
1823 \r
1824                                 next_plus += 1;\r
1825                         }\r
1826                 }\r
1827 \r
1828                 if ( token_type != gc_TokenOfOther ) {\r
1829                         e= HeapMemory_allocate( &token ); IF(e){goto fin;}\r
1830                         C_LanguageTokenClass_initConst( token );\r
1831                         token->Start = p;\r
1832                         token->Over  = p + next_plus;\r
1833                         token->TokenType = token_type;\r
1834 \r
1835                         e= ListClass_addLast( in_TokenList, &token->ListElement ); IF(e){goto fin;}\r
1836                         token = NULL;\r
1837                 }\r
1838 \r
1839                 p += next_plus;\r
1840                 c = *p;\r
1841         }\r
1842 \r
1843         e=0;\r
1844 fin:\r
1845         e= HeapMemory_free( &token, e );\r
1846         return  e;\r
1847 }\r
1848 \r
1849 \r
1850  \r
1851 /***********************************************************************\r
1852   <<< [CutComment_C_LanguageToken] >>> \r
1853 ************************************************************************/\r
1854 errnum_t  CutComment_C_LanguageToken( ListClass* /*<C_LanguageTokenClass>*/ TokenList )\r
1855 {\r
1856         errnum_t                e;\r
1857         C_LanguageTokenClass*   p;\r
1858         C_LanguageTokenEnum     token_type;\r
1859         bool                    is_in_c_comment;\r
1860         bool                    is_in_cpp_comment;\r
1861         bool                    is_cut;\r
1862         ListIteratorClass       iterator;\r
1863 \r
1864 \r
1865         is_in_c_comment = false;\r
1866         is_in_cpp_comment = false;\r
1867         e= ListClass_getListIterator( TokenList, &iterator ); IF(e){goto fin;}\r
1868         for (;;) {\r
1869                 p = (C_LanguageTokenClass*) ListIteratorClass_getNext( &iterator );\r
1870                         if ( p == NULL ) { break; }\r
1871                 ASSERT_D( p->ClassID == &g_C_LanguageTokenClass_ID,  e=E_OTHERS; goto fin );\r
1872 \r
1873                 token_type = p->TokenType;\r
1874                 if ( token_type == TwoChar8( '/', '*' ) ) {\r
1875                         if ( ! is_in_cpp_comment ) {\r
1876                                 is_in_c_comment = true;\r
1877                         }\r
1878                         is_cut = true;\r
1879                 }\r
1880                 else if ( token_type == TwoChar8( '*', '/' ) ) {\r
1881                         if ( ! is_in_cpp_comment ) {\r
1882                                 is_in_c_comment = false;\r
1883                         }\r
1884                         is_cut = true;\r
1885                 }\r
1886                 else if ( token_type == TwoChar8( '/', '/' ) ) {\r
1887                         if ( ! is_in_c_comment ) {\r
1888                                 is_in_cpp_comment = true;\r
1889                         }\r
1890                         is_cut = true;\r
1891                 }\r
1892                 else if ( token_type == '\n' ){\r
1893                         is_in_cpp_comment = false;\r
1894                         is_cut = true;\r
1895                 }\r
1896                 else {\r
1897                         is_cut = ( is_in_c_comment || is_in_cpp_comment );\r
1898                 }\r
1899 \r
1900                 if ( is_cut ) {\r
1901                         e= ListIteratorClass_remove( &iterator );\r
1902                         e= HeapMemory_free( &p, e ); \r
1903                 }\r
1904         }\r
1905 \r
1906         e=0;\r
1907 fin:\r
1908         return  e;\r
1909 }\r
1910 \r
1911 \r
1912  \r
1913 /***********************************************************************\r
1914 * Function: CutCommentC_1\r
1915 ************************************************************************/\r
1916 errnum_t  CutCommentC_1( const TCHAR*  in_InputPath,  const TCHAR*  in_OutputPath )\r
1917 {\r
1918         errnum_t   e;\r
1919         FILE*      file = NULL;\r
1920         TCHAR*     text = NULL;\r
1921         ListClass  tokens;\r
1922 \r
1923         ListClass_initConst( &tokens );\r
1924 \r
1925         e= FileT_openForRead( &file, in_InputPath ); IF(e){goto fin;}\r
1926         e= FileT_readAll( file, &text, NULL ); IF(e){goto fin;}\r
1927         e= FileT_closeAndNULL( &file, 0 ); IF(e){goto fin;}\r
1928 \r
1929         e= LexicalAnalize_C_Language( text, &tokens ); IF(e){goto fin;}\r
1930         e= FileT_openForWrite( &file, in_OutputPath, 0 ); IF(e){goto fin;}\r
1931         e= CopyWithoutComment_C_Language( &tokens, text, file ); IF(e){goto fin;}\r
1932         e= FileT_closeAndNULL( &file, 0 ); IF(e){goto fin;}\r
1933 \r
1934         e=0;\r
1935 fin:\r
1936         e= Delete_C_LanguageToken( &tokens, e );\r
1937         e= HeapMemory_free( &text, e );\r
1938         e= FileT_closeAndNULL( &file, e );\r
1939         return  e;\r
1940 }\r
1941 \r
1942 \r
1943  \r
1944 /***********************************************************************\r
1945 * Function: CopyWithoutComment_C_Language\r
1946 ************************************************************************/\r
1947 errnum_t  CopyWithoutComment_C_Language( ListClass*  in_Tokens,  TCHAR*  in_Text,  FILE*  in_OutStream )\r
1948 {\r
1949         errnum_t      e;\r
1950         const TCHAR*  p;\r
1951         TCHAR*        source = in_Text;\r
1952         TCHAR*        comment_start = NULL;\r
1953         TCHAR*        comment_over = NULL;\r
1954         bool          is_new_space = false;\r
1955 \r
1956         C_LanguageTokenClass* token;\r
1957         ListIteratorClass     iterator;\r
1958         const ClassID_Class*  class_ID;\r
1959 \r
1960 \r
1961         /* BOM \82È\82µ Unicode\81A\89ü\8ds=LF \82Å\95Û\91\82µ\82½\83t\83@\83C\83\8b\82Ì\93à\97e\82Æ\88ê\92v\82µ\82Ü\82·\81B */\r
1962 \r
1963 \r
1964         for ( ListClass_forEach( in_Tokens, &iterator, &token ) ) {\r
1965                 class_ID = token->ClassID;\r
1966                 if ( class_ID == &g_C_LanguageTokenClass_ID ) {\r
1967                         C_LanguageTokenEnum    token_type = token->TokenType;\r
1968 \r
1969                         if ( ( token_type == TwoChar8( '/', '*' )  ||  token_type == TwoChar8( '/', '/' )\r
1970                                         ) &&  source <= token->Start  &&  comment_start == NULL ) {\r
1971                                 p = token->Start;\r
1972                                 p = StrT_rskip( in_Text, p - 1, _T(" \t"), NULL );\r
1973 \r
1974                                 if ( p != NULL ) {\r
1975                                         comment_start = (TCHAR*) p + 1;\r
1976                                 } else {\r
1977                                         comment_start = in_Text;\r
1978                                 }\r
1979                                 if ( source > comment_start )\r
1980                                         { comment_start = source; }\r
1981 \r
1982 \r
1983                                 if ( token_type == TwoChar8( '/', '/' ) ) {\r
1984                                         p = StrT_chr( comment_start, _T('\n') );\r
1985                                         if ( p != NULL ) {\r
1986                                                 if ( comment_start == in_Text  ||  *( comment_start - 1 ) == _T('\n') )\r
1987                                                         { p += 1; }  /* This line has comment only */\r
1988                                         } else {\r
1989                                                 p = StrT_chr( comment_start,  _T('\0') );\r
1990                                         }\r
1991 \r
1992                                         comment_over = (TCHAR*) p;\r
1993                                 }\r
1994                         }\r
1995                         else if ( token_type == TwoChar8( '*', '/' )  &&  comment_start != NULL ) {\r
1996                                 p = token->Over;\r
1997                                 p = StrT_skip( p, _T(" \t") );\r
1998                                 if ( comment_start > in_Text ) {\r
1999                                         if ( *( comment_start - 1 ) == _T('\n') ) {\r
2000                                                 if ( *p == _T('\n') )\r
2001                                                         { p += 1; }\r
2002                                         }\r
2003                                         else if ( *p != _T('\n') ) {\r
2004                                                 /* Keeps spaces */\r
2005                                                 TCHAR*  p2 = _tcschr( comment_start, _T('/') );\r
2006 \r
2007                                                 if ( p2 != comment_start ) {\r
2008                                                         comment_start = p2;\r
2009                                                 } else {\r
2010                                                         is_new_space = true;\r
2011                                                 }\r
2012                                         }\r
2013                                 }\r
2014 \r
2015                                 comment_over = (TCHAR*) p;\r
2016                         }\r
2017 \r
2018 \r
2019                         if ( comment_over != NULL ) {\r
2020                                 e= FileT_writePart( in_OutStream,  source,  comment_start ); IF(e){goto fin;}\r
2021 \r
2022                                 if ( is_new_space ) {\r
2023                                         _TINT  rt= _fputtc( _T(' '), in_OutStream );\r
2024                                         IF(rt==_TEOF){e=E_OTHERS; goto fin;}\r
2025                                         is_new_space = false;\r
2026                                 }\r
2027 \r
2028                                 source = comment_over;\r
2029                                 comment_start = NULL;\r
2030                                 comment_over  = NULL;\r
2031                         }\r
2032                 }\r
2033         }\r
2034         e= FileT_writePart( in_OutStream,  source,  StrT_chr( source, _T('\0') ) ); IF(e){goto fin;}\r
2035 \r
2036         e=0;\r
2037 fin:\r
2038         return  e;\r
2039 }\r
2040 \r
2041 \r
2042  \r
2043 /***********************************************************************\r
2044   <<< [Delete_C_LanguageToken] >>> \r
2045 ************************************************************************/\r
2046 errnum_t  Delete_C_LanguageToken( ListClass* /*<C_LanguageTokenClass*>*/ TokenList, errnum_t e )\r
2047 {\r
2048         return  ListClass_finalizeWithVTable( TokenList, true, e );\r
2049 }\r
2050 \r
2051 \r
2052  \r
2053 /***********************************************************************\r
2054   <<< (C_LanguageTokenClass) >>> \r
2055 ************************************************************************/\r
2056 \r
2057 static const FinalizerVTableClass  gs_C_LanguageTokenClass_FinalizerVTable = {\r
2058         offsetof( C_LanguageTokenClass, FinalizerVTable ),\r
2059         DefaultFunction_Finalize,\r
2060 };\r
2061 static const PrintXML_VTableClass  gs_C_LanguageTokenClass_PrintXML_VTable = {\r
2062         offsetof( C_LanguageTokenClass, PrintXML_VTable ),\r
2063         C_LanguageTokenClass_printXML,\r
2064 };\r
2065 static const InterfaceToVTableClass  gs_C_LanguageTokenClass_InterfaceToVTables[] = {\r
2066         { &g_FinalizerInterface_ID, &gs_C_LanguageTokenClass_FinalizerVTable },\r
2067         { &g_PrintXML_Interface_ID, &gs_C_LanguageTokenClass_PrintXML_VTable },\r
2068 };\r
2069 static const ClassID_Class*  gs_C_LanguageTokenClass_SuperClassIDs[] = {\r
2070         &g_ClassID_SuperClass_ID, &g_ParsedRangeClass_ID, &g_SyntaxSubNodeClass_ID,\r
2071         &g_C_LanguageTokenClass_ID,\r
2072 };\r
2073 \r
2074 /*[g_C_LanguageTokenClass_ID]*/\r
2075 const ClassID_Class  g_C_LanguageTokenClass_ID = {\r
2076         "C_LanguageTokenClass",\r
2077         gs_C_LanguageTokenClass_SuperClassIDs,\r
2078         _countof( gs_C_LanguageTokenClass_SuperClassIDs ),\r
2079         sizeof( C_LanguageTokenClass ),\r
2080         NULL,\r
2081         gs_C_LanguageTokenClass_InterfaceToVTables,\r
2082         _countof( gs_C_LanguageTokenClass_InterfaceToVTables ),\r
2083 };\r
2084 \r
2085 \r
2086  \r
2087 /***********************************************************************\r
2088   <<< [C_LanguageTokenClass_initConst] >>> \r
2089 ************************************************************************/\r
2090 void  C_LanguageTokenClass_initConst( C_LanguageTokenClass* self )\r
2091 {\r
2092         self->ClassID = &g_C_LanguageTokenClass_ID;\r
2093         self->FinalizerVTable = &gs_C_LanguageTokenClass_FinalizerVTable;\r
2094         self->Start = NULL;\r
2095         self->Over = NULL;\r
2096         self->PrintXML_VTable = &gs_C_LanguageTokenClass_PrintXML_VTable;\r
2097         self->Parent = NULL;\r
2098         ListElementClass_initConst( &self->SubNodeListElement, self );\r
2099         self->TokenType = gc_TokenOfOther;\r
2100         ListElementClass_initConst( &self->ListElement, self );\r
2101         self->ParentBlock = NULL;\r
2102 }\r
2103 \r
2104 \r
2105  \r
2106 /***********************************************************************\r
2107   <<< [C_LanguageTokenClass_printXML] >>> \r
2108 ************************************************************************/\r
2109 errnum_t  C_LanguageTokenClass_printXML( C_LanguageTokenClass* self, FILE* OutputStream )\r
2110 {\r
2111         errnum_t  e;\r
2112         int  r;\r
2113 \r
2114         r= _ftprintf_s( OutputStream, _T("<C_LanguageTokenClass") );\r
2115                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2116 \r
2117 #if 0\r
2118         r= _ftprintf_s( OutputStream, _T(" Address=\"0x%08X\""), self );\r
2119                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2120 #endif\r
2121 \r
2122         r= _ftprintf_s( OutputStream, _T(" TokenType=\"%s\""),\r
2123                 C_LanguageTokenEnum_convertToStr( self->TokenType ) );\r
2124                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2125 \r
2126         r= _ftprintf_s( OutputStream, _T(" Token=\"") );\r
2127                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2128         e= ftcopy_part_r( OutputStream, self->Start, self->Over ); IF(e){goto fin;}\r
2129         r= _ftprintf_s( OutputStream, _T("\"") );\r
2130                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2131 \r
2132         r= _ftprintf_s( OutputStream, _T("/>\n") );\r
2133                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2134 \r
2135         e=0;\r
2136 fin:\r
2137         return  e;\r
2138 }\r
2139 \r
2140 \r
2141  \r
2142 /***********************************************************************\r
2143   <<< [C_LanguageTokenEnum_convertToStr] >>> \r
2144 ************************************************************************/\r
2145 \r
2146 static const NameAndNumClass  C_LanguageTokenEnum_ConvertTable[] = {\r
2147         { _T("Other"), gc_TokenOfOther },\r
2148         { _T("Number"), gc_TokenOfNumber },\r
2149         { _T("CIdentifier"), gc_TokenOfCIdentifier },\r
2150         { _T("("), gc_TokenOf_28 },\r
2151         { _T(")"), gc_TokenOf_29 },\r
2152         { _T("{"), gc_TokenOf_7B },\r
2153         { _T("}"), gc_TokenOf_7D },\r
2154         { _T("["), gc_TokenOf_5B },\r
2155         { _T("]"), gc_TokenOf_5D },\r
2156         { _T(":"), gc_TokenOf_3A },\r
2157         { _T(";"), gc_TokenOf_3B },\r
2158         { _T("*"), gc_TokenOf_2A },\r
2159         { _T("\\n"), gc_TokenOf_0A },\r
2160         { _T("/*"),  gc_TokenOf_2A2F },\r
2161         { _T("*/"),  gc_TokenOf_2F2A },\r
2162         { _T("//"),  gc_TokenOf_2F2F },\r
2163 };\r
2164 \r
2165 TCHAR*  C_LanguageTokenEnum_convertToStr( C_LanguageTokenEnum Value )\r
2166 {\r
2167         return  StrT_convertNumToStr( Value, C_LanguageTokenEnum_ConvertTable,\r
2168                 _countof( C_LanguageTokenEnum_ConvertTable ), _T("Unknown") );\r
2169 }\r
2170 \r
2171 \r
2172  \r
2173 /***********************************************************************\r
2174   <<< [Parse_PP_Directive] >>> \r
2175 ************************************************************************/\r
2176 \r
2177 errnum_t  Parse_PP_Directive_Step1( const TCHAR* Text, Set2* DirectivePointerArray );\r
2178 errnum_t  Parse_PP_Directive_ConnectIf( Set2* DirectivePointerArray );\r
2179 errnum_t  Parse_PP_Directive_Parameter( Set2* DirectivePointerArray );\r
2180 \r
2181 \r
2182 errnum_t  Parse_PP_Directive( const TCHAR* Text,\r
2183         Set2* /*<PP_DirectiveClass*>*/ DirectivePointerArray )\r
2184 {\r
2185         errnum_t  e;\r
2186 \r
2187         e= Parse_PP_Directive_Step1( Text, DirectivePointerArray ); IF(e){goto fin;}\r
2188         e= Parse_PP_Directive_ConnectIf( DirectivePointerArray ); IF(e){goto fin;}\r
2189         e= Parse_PP_Directive_Parameter( DirectivePointerArray ); IF(e){goto fin;}\r
2190 \r
2191         e=0;\r
2192 fin:\r
2193         return  e;\r
2194 }\r
2195 \r
2196 \r
2197 /*[Parse_PP_Directive_Step1]*/\r
2198 errnum_t  Parse_PP_Directive_Step1( const TCHAR* Text, Set2* DirectivePointerArray )\r
2199 {\r
2200         errnum_t      e;\r
2201         const TCHAR*  pos;\r
2202         const TCHAR*  p;\r
2203         PP_DirectiveClass*   directive = NULL;\r
2204         PP_DirectiveClass    directive_0;\r
2205         PP_DirectiveClass**  directive_pp;\r
2206         ClassID_Class*       class_ID;\r
2207 \r
2208         pos = Text;\r
2209         PP_DirectiveClass_initConst( &directive_0 );\r
2210 \r
2211         for (;;) {\r
2212 \r
2213                 /* Set "DirectiveName_Start" */\r
2214                 p = _tcschr( pos, _T('#') );\r
2215                 if ( p == NULL )\r
2216                         { break; }\r
2217                 p = StrT_skip( p + 1, _T(" \t") );\r
2218                         ASSERT_R( *p != _T('\0'), e=E_OTHERS; goto fin );\r
2219                 directive_0.DirectiveName_Start = p;\r
2220 \r
2221 \r
2222                 /* Set "DirectiveName_Over" */\r
2223                 directive_0.DirectiveName_Over =\r
2224                         StrT_searchOverOfCIdentifier( directive_0.DirectiveName_Start );\r
2225 \r
2226 \r
2227                 /* Set "Start" */\r
2228                 p = StrT_rstr( Text, directive_0.DirectiveName_Start, _T("\n"), NULL );\r
2229                 if ( p == NULL )  { p = Text; }\r
2230                 else              { p += 1; }\r
2231                 directive_0.Start = p;\r
2232 \r
2233 \r
2234                 /* Set "Over" */\r
2235                 p = directive_0.DirectiveName_Over;\r
2236                 for (;;) {\r
2237                         const TCHAR*  p2 = _tcschr( p, _T('\n') );\r
2238                         if ( p2 == NULL ) {\r
2239                                 p = _tcschr( p, _T('\0') );\r
2240                                 break;\r
2241                         } else if ( *( p2 - 1 ) == _T('\\') ) {\r
2242                                 p = p2 + 1;\r
2243                                 continue;\r
2244                         } else {\r
2245                                 p = p2 + 1;\r
2246                                 break;\r
2247                         }\r
2248                 }\r
2249                 directive_0.Over = p;\r
2250 \r
2251 \r
2252                 /* Set "directive" */\r
2253                 {\r
2254                         static NameOnlyClass  table[] = {\r
2255                                 { _T("define"), (void*) &g_PP_SharpDefineClass_ID },\r
2256                                 { _T("include"),(void*) &g_PP_SharpIncludeClass_ID },\r
2257                                 { _T("if"),     (void*) &g_PP_SharpIfClass_ID },\r
2258                                 { _T("else"),   (void*) &g_PP_SharpElseClass_ID },\r
2259                                 { _T("endif"),  (void*) &g_PP_SharpEndifClass_ID },\r
2260                                 { _T("ifdef"),  (void*) &g_PP_SharpIfdefClass_ID },\r
2261                                 { _T("ifndef"), (void*) &g_PP_SharpIfndefClass_ID },\r
2262                         };\r
2263 \r
2264                         class_ID = StrT_convPartStrToPointer(\r
2265                                 directive_0.DirectiveName_Start,\r
2266                                 directive_0.DirectiveName_Over,\r
2267                                 table, sizeof(table), (void*) &g_PP_DirectiveClass_ID );\r
2268                 }\r
2269 \r
2270                 e= ClassID_Class_createObject( class_ID, &directive, NULL ); IF(e){goto fin;}\r
2271 \r
2272                 directive->DirectiveName_Start = directive_0.DirectiveName_Start;\r
2273                 directive->DirectiveName_Over  = directive_0.DirectiveName_Over;\r
2274                 directive->Start = directive_0.Start;\r
2275                 directive->Over  = directive_0.Over;\r
2276 \r
2277 \r
2278                 /* Add to "DirectivePointerArray" (1) */\r
2279                 e= Set2_alloc( DirectivePointerArray, &directive_pp, PP_DirectiveClass* );\r
2280                         IF(e){goto fin;}\r
2281 \r
2282 \r
2283                 /* Add to "DirectivePointerArray" (2) */\r
2284                 *directive_pp = directive;\r
2285                 directive = NULL;\r
2286 \r
2287 \r
2288                 /* Next */\r
2289                 pos = directive_0.Over;\r
2290                 PP_DirectiveClass_initConst( &directive_0 );\r
2291         }\r
2292 \r
2293         e=0;\r
2294 fin:\r
2295         if ( directive != NULL )  { e= HeapMemory_free( &directive, e ); }\r
2296         return  e;\r
2297 }\r
2298 \r
2299 \r
2300 /*[Parse_PP_Directive_ConnectIf]*/\r
2301 errnum_t  Parse_PP_Directive_ConnectIf( Set2* DirectivePointerArray )\r
2302 {\r
2303         errnum_t             e;\r
2304         PP_DirectiveClass**  pp;\r
2305         PP_DirectiveClass**  pp_over;\r
2306         PP_DirectiveClass*   directive;\r
2307         PP_SharpIfClass**    pp_sh_if;  /* pp is pointer of pointer, sh = sharp */\r
2308         PP_SharpElseClass**  pp_sh_else;\r
2309         Set2                 if_stack;\r
2310         Set2                 else_stack;\r
2311         PP_SharpIfClass*     sh_if;          /* sh = sharp */\r
2312         PP_SharpElseClass*   sh_else;        /* sh = sharp */\r
2313         PP_SharpEndifClass*  sh_endif;       /* sh = sharp */\r
2314         PP_DirectiveClass*   sh_if_or_else;  /* sh = sharp */\r
2315 \r
2316 \r
2317         Set2_initConst( &if_stack );\r
2318         Set2_initConst( &else_stack );\r
2319         e= Set2_init( &if_stack, 0x10 ); IF(e){goto fin;}\r
2320         e= Set2_init( &else_stack, 0x10 ); IF(e){goto fin;}\r
2321         sh_if         = NULL;\r
2322         sh_else       = NULL;\r
2323         sh_endif      = NULL;\r
2324         sh_if_or_else = NULL;\r
2325 \r
2326         for ( Set2_forEach( DirectivePointerArray, &pp, &pp_over, PP_DirectiveClass* ) ) {\r
2327                 directive = *pp;\r
2328 \r
2329                 if ( ClassID_Class_isSuperClass( directive->ClassID, &g_PP_SharpIfClass_ID ) ) {\r
2330 \r
2331                         /* Start of nest */\r
2332                         if ( sh_if_or_else != NULL ) {\r
2333                                 e= Set2_alloc( &if_stack, &pp_sh_if, PP_SharpIfClass* );\r
2334                                         IF(e){goto fin;}\r
2335                                 *pp_sh_if = sh_if;\r
2336 \r
2337                                 e= Set2_alloc( &else_stack, &pp_sh_else, PP_SharpElseClass* );\r
2338                                         IF(e){goto fin;}\r
2339                                 *pp_sh_else = sh_else;\r
2340                         }\r
2341 \r
2342                         /* Set "sh_if" */\r
2343                         sh_if = (PP_SharpIfClass*) directive;\r
2344                         sh_if_or_else = directive;\r
2345                 }\r
2346                 else if ( directive->ClassID == &g_PP_SharpElseClass_ID ) {\r
2347                         sh_else = (PP_SharpElseClass*) directive;\r
2348 \r
2349                         IF ( sh_if == NULL ) {\r
2350                                 Error4_printf( _T("<ERROR msg=\"Not found #if\"/>") );\r
2351                                 e= E_ORIGINAL; goto fin;\r
2352                         }\r
2353 \r
2354                         /* Link #if and #else */\r
2355                         sh_if->NextDirective = directive;\r
2356                         sh_else->StartDirective = sh_if;\r
2357                         sh_if_or_else = directive;\r
2358                 }\r
2359                 else if ( directive->ClassID == &g_PP_SharpEndifClass_ID ) {\r
2360                         sh_endif = (PP_SharpEndifClass*) directive;\r
2361 \r
2362                         IF ( sh_if_or_else == NULL ) {\r
2363                                 Error4_printf( _T("<ERROR msg=\"Not found #if\"/>") );\r
2364                                 e= E_ORIGINAL; goto fin;\r
2365                         }\r
2366 \r
2367                         /* Link ( #if or #else ) and #endif */\r
2368                         sh_if->EndDirective = sh_endif;\r
2369                         if ( sh_else == NULL )\r
2370                                 { sh_if->NextDirective = directive; }\r
2371                         else\r
2372                                 { sh_else->EndDirective = sh_endif; }\r
2373                         sh_endif->StartDirective = sh_if;\r
2374                         sh_endif->PreviousDirective = sh_if_or_else;\r
2375 \r
2376                         sh_if         = NULL;\r
2377                         sh_else       = NULL;\r
2378                         sh_endif      = NULL;\r
2379                         sh_if_or_else = NULL;\r
2380 \r
2381                         /* End of nest */\r
2382                         if ( if_stack.Next > if_stack.First ) {\r
2383                                 e= Set2_pop( &if_stack, &pp_sh_if, PP_SharpIfClass* );\r
2384                                         IF(e){goto fin;}\r
2385                                 sh_if = *pp_sh_if;\r
2386 \r
2387                                 e= Set2_pop( &else_stack, &pp_sh_else, PP_SharpElseClass* );\r
2388                                         IF(e){goto fin;}\r
2389                                 sh_else = *pp_sh_else;\r
2390 \r
2391                                 if ( sh_else == NULL ) {\r
2392                                         sh_if_or_else = (PP_DirectiveClass*) sh_if;\r
2393                                 } else {\r
2394                                         sh_if_or_else = (PP_DirectiveClass*) sh_else;\r
2395                                 }\r
2396                         }\r
2397                 }\r
2398         }\r
2399 \r
2400         e=0;\r
2401 fin:\r
2402         e= Set2_finish( &if_stack, e );\r
2403         e= Set2_finish( &else_stack, e );\r
2404         return  e;\r
2405 }\r
2406 \r
2407 \r
2408 /*[Parse_PP_Directive_Parameter]*/\r
2409 errnum_t  Parse_PP_Directive_Parameter( Set2* DirectivePointerArray )\r
2410 {\r
2411         errnum_t             e;\r
2412         TCHAR*               p;\r
2413         PP_DirectiveClass**  pp;\r
2414         PP_DirectiveClass**  pp_over;\r
2415         PP_DirectiveClass*   directive;\r
2416 \r
2417         for ( Set2_forEach( DirectivePointerArray, &pp, &pp_over, PP_DirectiveClass* ) ) {\r
2418                 directive = *pp;\r
2419 \r
2420                 if ( ClassID_Class_isSuperClass( directive->ClassID, &g_PP_SharpDefineClass_ID ) ) {\r
2421                         PP_SharpDefineClass*  sh_define = (PP_SharpDefineClass*) directive;\r
2422 \r
2423                         p = StrT_skip( sh_define->DirectiveName_Over, _T(" \t") );\r
2424                         IF ( p >= sh_define->Over ) { e=E_OTHERS; goto fin; }\r
2425                         sh_define->Symbol_Start = p;\r
2426 \r
2427                         p = StrT_searchOverOfCIdentifier( p );\r
2428                         sh_define->Symbol_Over = p;\r
2429                 }\r
2430 \r
2431                 if ( ClassID_Class_isSuperClass( directive->ClassID, &g_PP_SharpIncludeClass_ID ) ) {\r
2432                         TCHAR*                 p;\r
2433                         TCHAR*                 closers;\r
2434                         PP_SharpIncludeClass*  sh_include = (PP_SharpIncludeClass*) directive;\r
2435 \r
2436                         p = StrT_skip( sh_include->DirectiveName_Over, _T(" \t") );\r
2437                         IF ( p >= sh_include->Over ) { e=E_OTHERS; goto fin; }\r
2438                         switch ( *p ) {\r
2439                                 case  '<':\r
2440                                         sh_include->PathBracket = _T('<');\r
2441                                         closers = _T(">");\r
2442                                         break;\r
2443 \r
2444                                 case  '"':\r
2445                                         sh_include->PathBracket = _T('"');\r
2446                                         closers = _T("\"");\r
2447                                         break;\r
2448 \r
2449                                 default:\r
2450                                         sh_include->PathBracket = _T('\0');\r
2451                                         closers = _T(" \t\n");\r
2452                                         break;\r
2453                         }\r
2454 \r
2455                         sh_include->Path_Start = p + 1;\r
2456 \r
2457                         p = StrT_chrs( p + 1, closers );\r
2458                                 IF ( p == NULL ) { e=E_OTHERS; goto fin; }\r
2459                         sh_include->Path_Over = p;\r
2460                 }\r
2461 \r
2462                 if ( ClassID_Class_isSuperClass( directive->ClassID, &g_PP_SharpIfdefClass_ID ) ) {\r
2463                         TCHAR*  p;\r
2464                         PP_SharpIfdefClass*  sh_ifdef;    /* sh = sharp */\r
2465 \r
2466                         sh_ifdef = (PP_SharpIfdefClass*) directive;\r
2467 \r
2468                         p = StrT_skip( sh_ifdef->DirectiveName_Over, _T(" \t") );\r
2469                         IF ( p >= sh_ifdef->Over ) { e=E_OTHERS; goto fin; }\r
2470                         sh_ifdef->Symbol_Start = p;\r
2471 \r
2472                         p = StrT_searchOverOfCIdentifier( p );\r
2473                         sh_ifdef->Symbol_Over = p;\r
2474                 }\r
2475         }\r
2476 \r
2477         e=0;\r
2478 fin:\r
2479         return  e;\r
2480 }\r
2481 \r
2482 \r
2483  \r
2484 /***********************************************************************\r
2485   <<< [Delete_PP_Directive] >>> \r
2486 ************************************************************************/\r
2487 errnum_t  Delete_PP_Directive( Set2* DirectivePointerArray, errnum_t e )\r
2488 {\r
2489         PP_DirectiveClass**    pp;\r
2490         PP_DirectiveClass**    pp_over;\r
2491         PP_DirectiveClass*     directive;\r
2492         FinalizerVTableClass*  finalizer;\r
2493 \r
2494         if ( Set2_isInited( DirectivePointerArray ) ) {\r
2495                 for ( Set2_forEach( DirectivePointerArray, &pp, &pp_over, PP_DirectiveClass* ) ) {\r
2496                         directive = *pp;\r
2497                         finalizer = ClassID_Class_getVTable( directive->ClassID,\r
2498                                 &g_FinalizerInterface_ID );\r
2499                         e= finalizer->Finalize( directive, e );\r
2500                         e= HeapMemory_free( &directive, e );\r
2501                 }\r
2502 \r
2503                 e= Set2_finish( DirectivePointerArray, e );\r
2504         }\r
2505         return  e;\r
2506 }\r
2507 \r
2508 \r
2509  \r
2510 /***********************************************************************\r
2511   <<< [CutPreprocessorDirectives_from_C_LanguageToken] >>> \r
2512 ************************************************************************/\r
2513 errnum_t  CutPreprocessorDirectives_from_C_LanguageToken(\r
2514         ListClass* /*<C_LanguageTokenClass*>*/ TokenList,\r
2515         Set2* /*<PP_DirectiveClass*>*/ Directives )\r
2516 {\r
2517         errnum_t                e;\r
2518         C_LanguageTokenClass*   token;\r
2519         ListIteratorClass       iterator;\r
2520         PP_DirectiveClass**     pp_directive = Directives->First;\r
2521         PP_DirectiveClass**     pp_directive_over = Directives->Next;\r
2522         PP_DirectiveClass*      directive = *pp_directive;\r
2523 \r
2524 \r
2525         if ( pp_directive == pp_directive_over )\r
2526                 { e=0;  goto fin; }\r
2527 \r
2528         e= ListClass_getListIterator( TokenList, &iterator ); IF(e){goto fin;}\r
2529         for (;;) {\r
2530                 token = (C_LanguageTokenClass*) ListIteratorClass_getNext( &iterator );\r
2531                         if ( token == NULL ) { break; }\r
2532                 ASSERT_D( token->ClassID == &g_C_LanguageTokenClass_ID,  e=E_OTHERS; goto fin );\r
2533 \r
2534                 if ( token->Start >= directive->Start ) {\r
2535                         if ( token->Over <= directive->Over ) {\r
2536                                 e= ListIteratorClass_remove( &iterator );\r
2537                                 e= HeapMemory_free( &token, 0 ); IF(e){goto fin;}\r
2538                         }\r
2539                         else {\r
2540                                 while ( token->Start > directive->Over ) {\r
2541                                         pp_directive += 1;\r
2542                                         if ( pp_directive >= pp_directive_over )\r
2543                                                 { break; }\r
2544                                         directive = *pp_directive;\r
2545                                 }\r
2546                         }\r
2547                 }\r
2548         }\r
2549 \r
2550         e=0;\r
2551 fin:\r
2552         return  e;\r
2553 }\r
2554 \r
2555 \r
2556  \r
2557 /***********************************************************************\r
2558   <<< (PP_DirectiveClass) >>> \r
2559 ************************************************************************/\r
2560 \r
2561 /*[PP_DirectiveClass_initConst]*/\r
2562 void  PP_DirectiveClass_initConst( PP_DirectiveClass* self )\r
2563 {\r
2564         self->ClassID  = &g_PP_DirectiveClass_ID;\r
2565         self->Start    = NULL;\r
2566         self->Over     = NULL;\r
2567         self->DirectiveName_Start = NULL;\r
2568         self->DirectiveName_Over  = NULL;\r
2569 }\r
2570 \r
2571 /*[g_PP_DirectiveClass_ID]*/\r
2572 static const ClassID_Class*  gs_PP_DirectiveClass_SuperClassIDs[] = {\r
2573         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID\r
2574 };\r
2575 static const FinalizerVTableClass  gs_PP_DirectiveClass_FinalizerVTable = {\r
2576         offsetof( PP_DirectiveClass, FinalizerVTable ),\r
2577         DefaultFunction_Finalize\r
2578 };\r
2579 static const InterfaceToVTableClass  gs_PP_DirectiveClass_InterfaceToVTables[] = {\r
2580         { &g_FinalizerInterface_ID, &gs_PP_DirectiveClass_FinalizerVTable }\r
2581 };\r
2582 const ClassID_Class  g_PP_DirectiveClass_ID = {\r
2583         "PP_DirectiveClass",\r
2584         gs_PP_DirectiveClass_SuperClassIDs,\r
2585         _countof( gs_PP_DirectiveClass_SuperClassIDs ),\r
2586         sizeof( PP_DirectiveClass ),\r
2587         NULL,\r
2588         gs_PP_DirectiveClass_InterfaceToVTables,\r
2589         _countof( gs_PP_DirectiveClass_InterfaceToVTables )\r
2590 };\r
2591 \r
2592 \r
2593 /*[g_PP_SharpDefineClass_ID]*/\r
2594 static const ClassID_Class*  gs_PP_SharpDefineClass_SuperClassIDs[] = {\r
2595         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID,\r
2596         &g_PP_DirectiveClass_ID\r
2597 };\r
2598 static const FinalizerVTableClass  gs_PP_SharpDefineClass_FinalizerVTable = {\r
2599         offsetof( PP_SharpDefineClass, FinalizerVTable ),\r
2600         DefaultFunction_Finalize\r
2601 };\r
2602 static const InterfaceToVTableClass  gs_PP_SharpDefineClass_InterfaceToVTables[] = {\r
2603         { &g_FinalizerInterface_ID, &gs_PP_SharpDefineClass_FinalizerVTable }\r
2604 };\r
2605 const ClassID_Class  g_PP_SharpDefineClass_ID = {\r
2606         "PP_SharpDefineClass",\r
2607         gs_PP_SharpDefineClass_SuperClassIDs,\r
2608         _countof( gs_PP_SharpDefineClass_SuperClassIDs ),\r
2609         sizeof( PP_SharpDefineClass ),\r
2610         NULL,\r
2611         gs_PP_SharpDefineClass_InterfaceToVTables,\r
2612         _countof( gs_PP_SharpDefineClass_InterfaceToVTables )\r
2613 };\r
2614 \r
2615 \r
2616 /*[g_PP_SharpIncludeClass_ID]*/\r
2617 static const ClassID_Class*  gs_PP_SharpIncludeClass_SuperClassIDs[] = {\r
2618         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID,\r
2619         &g_PP_DirectiveClass_ID\r
2620 };\r
2621 static const FinalizerVTableClass  gs_PP_SharpIncludeClass_FinalizerVTable = {\r
2622         offsetof( PP_SharpIncludeClass, FinalizerVTable ),\r
2623         DefaultFunction_Finalize\r
2624 };\r
2625 static const InterfaceToVTableClass  gs_PP_SharpIncludeClass_InterfaceToVTables[] = {\r
2626         { &g_FinalizerInterface_ID, &gs_PP_SharpIncludeClass_FinalizerVTable }\r
2627 };\r
2628 const ClassID_Class  g_PP_SharpIncludeClass_ID = {\r
2629         "PP_SharpIncludeClass",\r
2630         gs_PP_SharpIncludeClass_SuperClassIDs,\r
2631         _countof( gs_PP_SharpIncludeClass_SuperClassIDs ),\r
2632         sizeof( PP_SharpIncludeClass ),\r
2633         NULL,\r
2634         gs_PP_SharpIncludeClass_InterfaceToVTables,\r
2635         _countof( gs_PP_SharpIncludeClass_InterfaceToVTables )\r
2636 };\r
2637 \r
2638 \r
2639 /*[g_PP_SharpIfClass_ID]*/\r
2640 static const ClassID_Class*  gs_PP_SharpIfClass_SuperClassIDs[] = {\r
2641         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID,\r
2642         &g_PP_DirectiveClass_ID\r
2643 };\r
2644 static const FinalizerVTableClass  gs_PP_SharpIfClass_FinalizerVTable = {\r
2645         offsetof( PP_SharpIfClass, FinalizerVTable ),\r
2646         DefaultFunction_Finalize\r
2647 };\r
2648 static const InterfaceToVTableClass  gs_PP_SharpIfClass_InterfaceToVTables[] = {\r
2649         { &g_FinalizerInterface_ID, &gs_PP_SharpIfClass_FinalizerVTable }\r
2650 };\r
2651 const ClassID_Class  g_PP_SharpIfClass_ID = {\r
2652         "PP_SharpIfClass",\r
2653         gs_PP_SharpIfClass_SuperClassIDs,\r
2654         _countof( gs_PP_SharpIfClass_SuperClassIDs ),\r
2655         sizeof( PP_SharpIfClass ),\r
2656         NULL,\r
2657         gs_PP_SharpIfClass_InterfaceToVTables,\r
2658         _countof( gs_PP_SharpIfClass_InterfaceToVTables )\r
2659 };\r
2660 \r
2661 \r
2662 /*[g_PP_SharpElseClass_ID]*/\r
2663 static const ClassID_Class*  gs_PP_SharpElseClass_SuperClassIDs[] = {\r
2664         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID,\r
2665         &g_PP_DirectiveClass_ID\r
2666 };\r
2667 static const FinalizerVTableClass  gs_PP_SharpElseClass_FinalizerVTable = {\r
2668         offsetof( PP_SharpElseClass, FinalizerVTable ),\r
2669         DefaultFunction_Finalize\r
2670 };\r
2671 static const InterfaceToVTableClass  gs_PP_SharpElseClass_InterfaceToVTables[] = {\r
2672         { &g_FinalizerInterface_ID, &gs_PP_SharpElseClass_FinalizerVTable }\r
2673 };\r
2674 const ClassID_Class  g_PP_SharpElseClass_ID = {\r
2675         "PP_SharpElseClass",\r
2676         gs_PP_SharpElseClass_SuperClassIDs,\r
2677         _countof( gs_PP_SharpElseClass_SuperClassIDs ),\r
2678         sizeof( PP_SharpElseClass ),\r
2679         NULL,\r
2680         gs_PP_SharpElseClass_InterfaceToVTables,\r
2681         _countof( gs_PP_SharpElseClass_InterfaceToVTables )\r
2682 };\r
2683 \r
2684 \r
2685 /*[g_PP_SharpEndifClass_ID]*/\r
2686 static const ClassID_Class*  gs_PP_SharpEndifClass_SuperClassIDs[] = {\r
2687         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID,\r
2688         &g_PP_DirectiveClass_ID\r
2689 };\r
2690 static const FinalizerVTableClass  gs_PP_SharpEndifClass_FinalizerVTable = {\r
2691         offsetof( PP_SharpEndifClass, FinalizerVTable ),\r
2692         DefaultFunction_Finalize\r
2693 };\r
2694 static const InterfaceToVTableClass  gs_PP_SharpEndifClass_InterfaceToVTables[] = {\r
2695         { &g_FinalizerInterface_ID, &gs_PP_SharpEndifClass_FinalizerVTable }\r
2696 };\r
2697 const ClassID_Class  g_PP_SharpEndifClass_ID = {\r
2698         "PP_SharpEndifClass",\r
2699         gs_PP_SharpEndifClass_SuperClassIDs,\r
2700         _countof( gs_PP_SharpEndifClass_SuperClassIDs ),\r
2701         sizeof( PP_SharpEndifClass ),\r
2702         NULL,\r
2703         gs_PP_SharpEndifClass_InterfaceToVTables,\r
2704         _countof( gs_PP_SharpEndifClass_InterfaceToVTables )\r
2705 };\r
2706 \r
2707 \r
2708 /*[g_PP_SharpIfdefClass_ID]*/\r
2709 static const ClassID_Class*  gs_PP_SharpIfdefClass_SuperClassIDs[] = {\r
2710         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID,\r
2711         &g_PP_DirectiveClass_ID, &g_PP_SharpIfClass_ID\r
2712 };\r
2713 static const FinalizerVTableClass  gs_PP_SharpIfdefClass_FinalizerVTable = {\r
2714         offsetof( PP_SharpIfdefClass, FinalizerVTable ),\r
2715         DefaultFunction_Finalize\r
2716 };\r
2717 static const InterfaceToVTableClass  gs_PP_SharpIfdefClass_InterfaceToVTables[] = {\r
2718         { &g_FinalizerInterface_ID, &gs_PP_SharpIfdefClass_FinalizerVTable }\r
2719 };\r
2720 const ClassID_Class  g_PP_SharpIfdefClass_ID = {\r
2721         "PP_SharpIfdefClass",\r
2722         gs_PP_SharpIfdefClass_SuperClassIDs,\r
2723         _countof( gs_PP_SharpIfdefClass_SuperClassIDs ),\r
2724         sizeof( PP_SharpIfdefClass ),\r
2725         NULL,\r
2726         gs_PP_SharpIfdefClass_InterfaceToVTables,\r
2727         _countof( gs_PP_SharpIfdefClass_InterfaceToVTables )\r
2728 };\r
2729 \r
2730 \r
2731 /*[g_PP_SharpIfndefClass_ID]*/\r
2732 static const ClassID_Class*  gs_PP_SharpIfndefClass_SuperClassIDs[] = {\r
2733         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID,\r
2734         &g_PP_DirectiveClass_ID, &g_PP_SharpIfClass_ID, &g_PP_SharpIfdefClass_ID\r
2735 };\r
2736 static const FinalizerVTableClass  gs_PP_SharpIfndefClass_FinalizerVTable = {\r
2737         offsetof( PP_SharpIfndefClass, FinalizerVTable ),\r
2738         DefaultFunction_Finalize\r
2739 };\r
2740 static const InterfaceToVTableClass  gs_PP_SharpIfndefClass_InterfaceToVTables[] = {\r
2741         { &g_FinalizerInterface_ID, &gs_PP_SharpIfndefClass_FinalizerVTable }\r
2742 };\r
2743 \r
2744 const ClassID_Class  g_PP_SharpIfndefClass_ID = {\r
2745         "PP_SharpIfndefClass",\r
2746         gs_PP_SharpIfndefClass_SuperClassIDs,\r
2747         _countof( gs_PP_SharpIfndefClass_SuperClassIDs ),\r
2748         sizeof( PP_SharpIfndefClass ),\r
2749         NULL,\r
2750         gs_PP_SharpIfndefClass_InterfaceToVTables,\r
2751         _countof( gs_PP_SharpIfndefClass_InterfaceToVTables )\r
2752 };\r
2753 \r
2754 \r
2755  \r
2756 /***********************************************************************\r
2757   <<< (SyntaxSubNodeClass) >>> \r
2758 ************************************************************************/\r
2759 \r
2760 /*[g_SyntaxSubNodeClass_ID]*/\r
2761 const ClassID_Class  g_SyntaxSubNodeClass_ID = {\r
2762         "SyntaxSubNodeClass",\r
2763         NULL,\r
2764         0,\r
2765         sizeof( SyntaxSubNodeClass ),\r
2766         NULL,\r
2767         NULL,\r
2768         0,\r
2769 };\r
2770 \r
2771 \r
2772  \r
2773 /***********************************************************************\r
2774   <<< [Delete_SyntaxNodeList] >>> \r
2775 ************************************************************************/\r
2776 errnum_t  Delete_SyntaxNodeList( ListClass* /*<SyntaxNodeClass*>*/ NodeList, errnum_t e )\r
2777 {\r
2778         return  ListClass_finalizeWithVTable( NodeList, true, e );\r
2779 }\r
2780 \r
2781 \r
2782  \r
2783 /***********************************************************************\r
2784   <<< (SyntaxNodeClass) >>> \r
2785 ************************************************************************/\r
2786 \r
2787 static const FinalizerVTableClass  gs_SyntaxNodeClass_FinalizerVTable = {\r
2788         offsetof( SyntaxNodeClass, FinalizerVTable ),\r
2789         DefaultFunction_Finalize,\r
2790 };\r
2791 static const PrintXML_VTableClass  gs_SyntaxNodeClass_PrintXML_VTable = {\r
2792         offsetof( SyntaxNodeClass, PrintXML_VTable ),\r
2793         SyntaxNodeClass_printXML,\r
2794 };\r
2795 static const InterfaceToVTableClass  gs_SyntaxNodeClass_InterfaceToVTables[] = {\r
2796         { &g_FinalizerInterface_ID, &gs_SyntaxNodeClass_FinalizerVTable },\r
2797         { &g_PrintXML_Interface_ID, &gs_SyntaxNodeClass_PrintXML_VTable },\r
2798 };\r
2799 static const ClassID_Class*  gs_SyntaxNodeClass_SuperClassIDs[] = {\r
2800         &g_ClassID_SuperClass_ID, &g_ParsedRangeClass_ID, &g_SyntaxSubNodeClass_ID,\r
2801         &g_SyntaxNodeClass_ID,\r
2802 };\r
2803 \r
2804 /*[g_SyntaxNodeClass_ID]*/\r
2805 const ClassID_Class  g_SyntaxNodeClass_ID = {\r
2806         "SyntaxNodeClass",\r
2807         gs_SyntaxNodeClass_SuperClassIDs,\r
2808         _countof( gs_SyntaxNodeClass_SuperClassIDs ),\r
2809         sizeof( SyntaxNodeClass ),\r
2810         NULL,\r
2811         gs_SyntaxNodeClass_InterfaceToVTables,\r
2812         _countof( gs_SyntaxNodeClass_InterfaceToVTables ),\r
2813 };\r
2814 \r
2815 \r
2816  \r
2817 /***********************************************************************\r
2818   <<< [SyntaxNodeClass_initConst] >>> \r
2819 ************************************************************************/\r
2820 void  SyntaxNodeClass_initConst( SyntaxNodeClass* self )\r
2821 {\r
2822         self->ClassID = &g_SyntaxNodeClass_ID;\r
2823         self->FinalizerVTable = &gs_SyntaxNodeClass_FinalizerVTable;\r
2824         self->Start = NULL;\r
2825         self->Over = NULL;\r
2826         self->PrintXML_VTable = &gs_SyntaxNodeClass_PrintXML_VTable;\r
2827         self->Parent = NULL;\r
2828         ListElementClass_initConst( &self->SubNodeListElement, self );\r
2829         ListClass_initConst( &self->SubNodeList );\r
2830         ListElementClass_initConst( &self->ListElement, self );\r
2831 }\r
2832 \r
2833 \r
2834  \r
2835 /***********************************************************************\r
2836   <<< [SyntaxNodeClass_printXML] >>> \r
2837 ************************************************************************/\r
2838 errnum_t  SyntaxNodeClass_printXML( SyntaxNodeClass* self, FILE* OutputStream )\r
2839 {\r
2840         errnum_t  e;\r
2841         int  r;\r
2842 \r
2843         r= _ftprintf_s( OutputStream, _T("<SyntaxNodeClass") );\r
2844                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2845 \r
2846         r= _ftprintf_s( OutputStream, _T(" Address=\"0x%08X\""), self );\r
2847                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2848 \r
2849         r= _ftprintf_s( OutputStream, _T("/>\n") );\r
2850                 IF ( r < 0 ) { e=E_ACCESS_DENIED; goto fin; }\r
2851 \r
2852         e=0;\r
2853 fin:\r
2854         return  e;\r
2855 }\r
2856 \r
2857 \r
2858  \r
2859 /***********************************************************************\r
2860   <<< [SyntaxNodeClass_addSubNode] >>> \r
2861 ************************************************************************/\r
2862 errnum_t  SyntaxNodeClass_addSubNode( SyntaxNodeClass* self, SyntaxSubNodeClass* SubNode )\r
2863 {\r
2864         errnum_t  e;\r
2865 \r
2866         ASSERT_D( ClassID_Class_isSuperClass( self->ClassID, &g_SyntaxNodeClass_ID ), e=E_OTHERS; goto fin );\r
2867         ASSERT_D( ClassID_Class_isSuperClass( SubNode->ClassID, &g_SyntaxSubNodeClass_ID ), e=E_OTHERS; goto fin );\r
2868         ASSERT_R( SubNode->Parent == NULL, e=E_OTHERS; goto fin );\r
2869 \r
2870         e= ListClass_addLast( &self->SubNodeList, &SubNode->SubNodeListElement ); IF(e){goto fin;}\r
2871         SubNode->Parent = self;\r
2872 \r
2873         e=0;\r
2874 fin:\r
2875         return  e;\r
2876 }\r
2877 \r
2878 \r
2879  \r
2880 /***********************************************************************\r
2881   <<< [LineNumberIndexClass_compare_sub] >>> \r
2882 ************************************************************************/\r
2883 int  LineNumberIndexClass_compare_sub( const void* ppLeft, const void* ppRight, const void* Param,\r
2884         int* out_Result )\r
2885 {\r
2886         UNREFERENCED_VARIABLE( Param );\r
2887         *out_Result = (const uint8_t*) *(TCHAR**) ppLeft - (const uint8_t*) *(TCHAR**) ppRight;\r
2888         return  0;\r
2889 }\r
2890 \r
2891 \r
2892  \r
2893 /***********************************************************************\r
2894   <<< (LineNumberIndexClass) >>> \r
2895 ************************************************************************/\r
2896 \r
2897 /*[LineNumberIndexClass_initConst]*/\r
2898 void  LineNumberIndexClass_initConst( LineNumberIndexClass* self )\r
2899 {\r
2900         Set2_initConst( &self->LeftsOfLine );\r
2901 }\r
2902 \r
2903 \r
2904 /*[LineNumberIndexClass_finalize]*/\r
2905 errnum_t  LineNumberIndexClass_finalize( LineNumberIndexClass* self, errnum_t e )\r
2906 {\r
2907         return  Set2_finish( &self->LeftsOfLine, e );\r
2908 }\r
2909 \r
2910 \r
2911 /*[LineNumberIndexClass_initialize]*/\r
2912 errnum_t  LineNumberIndexClass_initialize( LineNumberIndexClass* self, const TCHAR* Text )\r
2913 {\r
2914         errnum_t       e;\r
2915         const TCHAR*   p;\r
2916         const TCHAR*   line_feed;\r
2917         const TCHAR**  pp_left;\r
2918 \r
2919         e= Set2_init( &self->LeftsOfLine, 1000 * sizeof(TCHAR*) ); IF(e){goto fin;}\r
2920 \r
2921         p = Text;\r
2922         for (;;) {\r
2923                 e= Set2_alloc( &self->LeftsOfLine, &pp_left, const TCHAR* ); IF(e){goto fin;}\r
2924                 *pp_left = p;\r
2925 \r
2926                 line_feed = _tcschr( p, _T('\n') );\r
2927                 if ( line_feed == NULL )\r
2928                         { break; }\r
2929 \r
2930                 p = line_feed + 1;\r
2931         }\r
2932 \r
2933 #if 0 //[TODO]\r
2934         p = _tcschr( p, _T('\0') );\r
2935         e= Set2_alloc( &self->LeftsOfLine, &pp_left, const TCHAR* ); IF(e){goto fin;}\r
2936         *pp_left = p + 1;\r
2937 #else\r
2938         if ( *p != _T('\0') ) {\r
2939                 p = _tcschr( p, _T('\0') );\r
2940                 e= Set2_alloc( &self->LeftsOfLine, &pp_left, const TCHAR* ); IF(e){goto fin;}\r
2941                 *pp_left = p + 1;\r
2942 #endif\r
2943         }\r
2944 \r
2945         e=0;\r
2946 fin:\r
2947         return  e;\r
2948 }\r
2949 \r
2950 \r
2951 /*[LineNumberIndexClass_searchLineNumber]*/\r
2952 errnum_t  LineNumberIndexClass_searchLineNumber( LineNumberIndexClass* self, const TCHAR* Position,\r
2953         int* out_LineNumber )\r
2954 {\r
2955         errnum_t  e;\r
2956         int       found_index;\r
2957         int       result;\r
2958 \r
2959         e= PArray_doBinarySearch( self->LeftsOfLine.First,\r
2960                 (uint8_t*) self->LeftsOfLine.Next - (uint8_t*) self->LeftsOfLine.First,\r
2961                 Position, LineNumberIndexClass_compare_sub, NULL,\r
2962                 &found_index, &result );\r
2963                 IF(e){goto fin;}\r
2964 \r
2965         *out_LineNumber = found_index + 1;\r
2966 \r
2967         e=0;\r
2968 fin:\r
2969         return  e;\r
2970 }\r
2971 \r
2972 \r
2973 /*[LineNumberIndexClass_getCountOfLines]*/\r
2974 int  LineNumberIndexClass_getCountOfLines( LineNumberIndexClass* self )\r
2975 {\r
2976         return  Set2_getCount( &self->LeftsOfLine, const TCHAR* ) - 1;\r
2977 }\r
2978 \r
2979 \r
2980  \r
2981 /***********************************************************************\r
2982   <<< (ParsedRangeClass) >>> \r
2983 ************************************************************************/\r
2984 \r
2985 /*[ParsedRangeClass_initConst]*/\r
2986 void  ParsedRangeClass_initConst( ParsedRangeClass* self )\r
2987 {\r
2988         self->ClassID = &g_ParsedRangeClass_ID;\r
2989         self->FinalizerVTable = NULL;\r
2990         self->StaticAddress = NULL;\r
2991         self->Start = NULL;\r
2992         self->Over = NULL;\r
2993 }\r
2994 \r
2995 \r
2996 /*[g_ParsedRangeClass_ID]*/\r
2997 static const ClassID_Class*  gs_ParsedRangeClass_SuperClassIDs[] = {\r
2998         &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID, &g_ParsedRangeClass_ID\r
2999 };\r
3000 const ClassID_Class  g_ParsedRangeClass_ID = {\r
3001         "ParsedRangeClass",\r
3002         gs_ParsedRangeClass_SuperClassIDs,\r
3003         _countof( gs_ParsedRangeClass_SuperClassIDs ),\r
3004         sizeof( ParsedRangeClass ),\r
3005         NULL,\r
3006 };\r
3007 \r
3008 \r
3009  \r
3010 /***********************************************************************\r
3011   <<< [ParsedRanges_getCut_by_PP_Directive] >>> \r
3012 ************************************************************************/\r
3013 errnum_t  ParsedRanges_getCut_by_PP_Directive(\r
3014         Set2* /*<ParsedRangeClass>*/    CutRanges,\r
3015         Set2* /*<PP_DirectiveClass*>*/  DirectivePointerArray,\r
3016         const TCHAR* Symbol,  bool IsCutDefine )\r
3017 {\r
3018         errnum_t             e;\r
3019         PP_DirectiveClass**  p;\r
3020         PP_DirectiveClass**  p_over;\r
3021 \r
3022         for ( Set2_forEach( DirectivePointerArray, &p, &p_over, PP_DirectiveClass* ) ) {\r
3023                 PP_DirectiveClass*  directive = *p;\r
3024                 PP_SharpIfClass*    sh_if = NULL;  /* sh = sharp */\r
3025                 bool                is_not_condition = false;\r
3026 \r
3027                 if ( ClassID_Class_isSuperClass( directive->ClassID, &g_PP_SharpIfdefClass_ID ) ) {\r
3028                         PP_SharpIfdefClass*  sh_ifdef = (PP_SharpIfdefClass*) directive;  /* sh = sharp */\r
3029 \r
3030                         if ( StrT_cmp_part( sh_ifdef->Symbol_Start, sh_ifdef->Symbol_Over, Symbol ) == 0 ) {\r
3031                                 sh_if = (PP_SharpIfClass*) sh_ifdef;\r
3032                                 is_not_condition = ( sh_ifdef->ClassID == &g_PP_SharpIfndefClass_ID );\r
3033                         }\r
3034                 }\r
3035                 else if ( directive->ClassID == &g_PP_SharpIfClass_ID ) {\r
3036                         const TCHAR*  condition_start;\r
3037                         const TCHAR*  condition_over;\r
3038 \r
3039                         sh_if = (PP_SharpIfClass*) directive;  /* sh = sharp */\r
3040                         condition_start = sh_if->DirectiveName_Over;\r
3041                         condition_over  = sh_if->Over;\r
3042 \r
3043                         while ( condition_start < condition_over ) {\r
3044                                 if ( _istspace( *condition_start ) ) {\r
3045                                         condition_start += 1;\r
3046                                 } else {\r
3047                                         break;\r
3048                                 }\r
3049                         }\r
3050                         while ( condition_start < condition_over ) {\r
3051                                 if ( _istspace( *( condition_over - 1 ) ) ) {\r
3052                                         condition_over -= 1;\r
3053                                 } else {\r
3054                                         break;\r
3055                                 }\r
3056                         }\r
3057                         if ( ! StrT_cmp_part( condition_start, condition_over, Symbol ) == 0 ) {\r
3058                                 sh_if = NULL;\r
3059                         }\r
3060                 }\r
3061 \r
3062                 if ( sh_if != NULL ) {\r
3063                         PP_SharpElseClass*   sh_else;   /* sh = sharp */\r
3064                         PP_SharpEndifClass*  sh_endif;  /* sh = sharp */\r
3065                         ParsedRangeClass*    cut;\r
3066 \r
3067 \r
3068                         /* Set "sh_else", "sh_endif" */\r
3069                         if ( ClassID_Class_isSuperClass( sh_if->NextDirective->ClassID,\r
3070                                         &g_PP_SharpElseClass_ID ) ) {\r
3071                                 sh_else = (PP_SharpElseClass*) sh_if->NextDirective;\r
3072                                 sh_endif = sh_if->EndDirective;\r
3073                         } else {\r
3074                                 sh_else = NULL;\r
3075                                 sh_endif = (PP_SharpEndifClass*) sh_if->NextDirective;\r
3076                         }\r
3077 \r
3078 \r
3079                         /* Add to "CutRanges" */\r
3080                         e= Set2_alloc( CutRanges, &cut, ParsedRangeClass ); IF(e){goto fin;}\r
3081                         cut->Start = sh_if->Start;\r
3082                         if ( is_not_condition == ! IsCutDefine ) {\r
3083                                 if ( sh_else != NULL ) {\r
3084                                         cut->Over = sh_else->Over;\r
3085 \r
3086                                         e= Set2_alloc( CutRanges, &cut, ParsedRangeClass );\r
3087                                                 IF(e){goto fin;}\r
3088                                         cut->Start = sh_endif->Start;\r
3089                                 }\r
3090                                 cut->Over = sh_endif->Over;\r
3091                         }\r
3092                         else {\r
3093                                 cut->Over = sh_if->Over;\r
3094 \r
3095                                 e= Set2_alloc( CutRanges, &cut, ParsedRangeClass );\r
3096                                         IF(e){goto fin;}\r
3097                                 if ( sh_else != NULL ) {\r
3098                                         cut->Start = sh_else->Start;\r
3099                                 } else {\r
3100                                         cut->Start = sh_endif->Start;\r
3101                                 }\r
3102                                 cut->Over = sh_endif->Over;\r
3103                         }\r
3104                 }\r
3105         }\r
3106 \r
3107         e=0;\r
3108 fin:\r
3109         return  e;\r
3110 }\r
3111 \r
3112 \r
3113  \r
3114 /***********************************************************************\r
3115   <<< [ParsedRangeClass_onInitializedForDebug] >>> \r
3116 ************************************************************************/\r
3117 #if ! defined( NDEBUG )\r
3118 void  ParsedRangeClass_onInitializedForDebug( ParsedRangeClass* self )\r
3119 {\r
3120         /* These code can be modified for Debug. */\r
3121         #if 0  // IS_USED_DEBUG_CHECK_CLASS\r
3122                 TCHAR*     text;\r
3123                 ptrdiff_t  break_diff = 0x1FA6A;\r
3124 \r
3125                 START_D( 10 );\r
3126                 text = GET_D( 1, TCHAR* );\r
3127                 PointerType_plus( &text, break_diff );\r
3128                 if ( text == self->Start ) {\r
3129                         if ( self->ClassID == &g_ParsedRangeClass_ID ) {\r
3130                                 SET_D( 2, self );\r
3131                         }\r
3132                 }\r
3133                 END_D();\r
3134         #else\r
3135                 UNREFERENCED_VARIABLE( self );\r
3136         #endif\r
3137 }\r
3138 #endif\r
3139 \r
3140 \r
3141  \r
3142 /***********************************************************************\r
3143   <<< [ParsedRanges_compareByStart] >>> \r
3144 ************************************************************************/\r
3145 int  ParsedRanges_compareByStart( const void* _a1, const void* _a2 )\r
3146 {\r
3147         ParsedRangeClass*  a1 = (ParsedRangeClass*) _a1;\r
3148         ParsedRangeClass*  a2 = (ParsedRangeClass*) _a2;\r
3149 \r
3150         return  a1->Start - a2->Start;\r
3151 }\r
3152 \r
3153 \r
3154  \r
3155 /***********************************************************************\r
3156   <<< [ParsedRanges_write_by_Cut] >>> \r
3157 ************************************************************************/\r
3158 errnum_t  ParsedRanges_write_by_Cut(\r
3159         Set2* /*<ParsedRangeClass>*/ CutRanges,\r
3160         const TCHAR* Text, FILE* OutFile )\r
3161 {\r
3162         errnum_t           e;\r
3163         const TCHAR*       position;\r
3164         ParsedRangeClass*  p;\r
3165         ParsedRangeClass*  p_over;\r
3166 \r
3167         qsort( CutRanges->First, Set2_getCount( CutRanges, ParsedRangeClass ),\r
3168                 sizeof(ParsedRangeClass), ParsedRanges_compareByStart );\r
3169 \r
3170         position = Text;\r
3171         for ( Set2_forEach( CutRanges, &p, &p_over, ParsedRangeClass ) ) {\r
3172                 const TCHAR*  cut_start_position;\r
3173                 const TCHAR*  cut_over_position;\r
3174 \r
3175                 cut_start_position = p->Start;\r
3176                 if ( position < cut_start_position ) {\r
3177                         e= FileT_writePart( OutFile, (TCHAR*)position, (TCHAR*)cut_start_position );\r
3178                                 IF(e){goto fin;}\r
3179                 }\r
3180 \r
3181                 cut_over_position = p->Over;\r
3182                 if ( position < cut_over_position ) {\r
3183                         position = cut_over_position;\r
3184                 }\r
3185         }\r
3186         _fputts( position, OutFile ); IF(ferror(OutFile)){e=E_ERRNO; goto fin;}\r
3187 \r
3188         e=0;\r
3189 fin:\r
3190         return  e;\r
3191 }\r
3192 \r
3193 \r
3194  \r
3195 /*=================================================================*/\r
3196 /* <<< [Locale/Locale.c] >>> */ \r
3197 /*=================================================================*/\r
3198  \r
3199 /***********************************************************************\r
3200   <<< [g_LocaleSymbol] >>> \r
3201 ************************************************************************/\r
3202 char*  g_LocaleSymbol = "";\r
3203 \r
3204 \r
3205  \r
3206 /***********************************************************************\r
3207   <<< [Locale_init] >>> \r
3208 ************************************************************************/\r
3209 int  Locale_init()\r
3210 {\r
3211         g_LocaleSymbol = ".OCP";\r
3212         setlocale( LC_ALL, ".OCP" );\r
3213         return  0;\r
3214 }\r
3215 \r
3216 \r
3217  \r
3218 /***********************************************************************\r
3219   <<< [Locale_isInited] >>> \r
3220 ************************************************************************/\r
3221 int  Locale_isInited()\r
3222 {\r
3223         return  ( g_LocaleSymbol[0] != '\0' );\r
3224                 // \82±\82±\82ª false \82ð\95Ô\82·\82Æ\82«\82Ì\91Î\8f\88\96@\82Í\81ALocale_isInited \82Ì\83w\83\8b\83v\82ð\8eQ\8fÆ\82µ\82Ä\82­\82¾\82³\82¢\81B\r
3225 }\r
3226 \r
3227 \r
3228  \r
3229 /*=================================================================*/\r
3230 /* <<< [IniFile2/IniFile2.c] >>> */ \r
3231 /*=================================================================*/\r
3232  \r
3233 /***********************************************************************\r
3234   <<< [IniStr_isLeft] >>> \r
3235 ************************************************************************/\r
3236 bool  IniStr_isLeft( const TCHAR* line, const TCHAR* symbol )\r
3237 {\r
3238   const TCHAR*  p;\r
3239   size_t  symbol_len = _tcslen( symbol );\r
3240 \r
3241   /* Skip spaces at the top of line */\r
3242   for ( p = line; *p == _T(' ') || *p == _T('\t'); p++ );\r
3243 \r
3244   /* Compare symbol */\r
3245   if ( _tcsnicmp( p, symbol, symbol_len ) != 0 )  return false;\r
3246 \r
3247   switch ( *(p + symbol_len) ) {\r
3248     case _T(' '):  case _T('\t'):  case _T('='):  return  true;\r
3249     default:  return  false;\r
3250   }\r
3251 }\r
3252 \r
3253 \r
3254 \r
3255  \r
3256 /***********************************************************************\r
3257   <<< [IniStr_refRight] >>> \r
3258 ************************************************************************/\r
3259 TCHAR*  IniStr_refRight( const TCHAR* line, bool bTrimRight )\r
3260 {\r
3261   const TCHAR*  p;\r
3262 \r
3263   for ( p = line; *p != _T('\0') && *p != _T('='); p++ );\r
3264   if ( *p == _T('=') ) {\r
3265 \r
3266     //=== Skip spaces at the right of equal. Trim the left of value\r
3267     for ( p++ ; *p == _T(' ') || *p == _T('\t'); p++ );\r
3268 \r
3269     //=== Trim the right of value\r
3270     if ( bTrimRight ) {\r
3271       const TCHAR*  t;\r
3272       TCHAR  c;\r
3273 \r
3274       t = StrT_chr( p, _T('\0') );\r
3275       if ( t != p ) {\r
3276         for ( t--; ; t-- ) {\r
3277           if ( t < p )\r
3278             { p = StrT_chr( p, _T('\0') );  break; }\r
3279 \r
3280           c = *t;\r
3281           if ( c != ' ' && c != '\t' && c != '\n' && c != '\r' )\r
3282             { *(TCHAR*)(t+1) = _T('\0');  break; }\r
3283         }\r
3284       }\r
3285     }\r
3286   }\r
3287   return  (TCHAR*) p;\r
3288 }\r
3289 \r
3290 \r
3291  \r
3292 /*=================================================================*/\r
3293 /* <<< [FileT/FileT.c] >>> */ \r
3294 /*=================================================================*/\r
3295  \r
3296 /***********************************************************************\r
3297   <<< [FileT_isExist] >>> \r
3298 ************************************************************************/\r
3299 bool  FileT_isExist( const TCHAR* path )\r
3300 {\r
3301  #if ! FileT_isExistWildcard\r
3302 \r
3303         DWORD  r;\r
3304 \r
3305         if ( path[0] == _T('\0') )  return  false;\r
3306         r = GetFileAttributes( path );\r
3307         return  r != (DWORD)-1;\r
3308 \r
3309  #else\r
3310 \r
3311         HANDLE  find;\r
3312         WIN32_FIND_DATA  data;\r
3313 \r
3314         find = FindFirstFileEx( path, FindExInfoStandard, &data,\r
3315                 FindExSearchNameMatch, NULL, 0 );\r
3316 \r
3317         if ( find == INVALID_HANDLE_VALUE ) {\r
3318                 return  false;\r
3319         }\r
3320         else {\r
3321                 FindClose( find );\r
3322                 return  true;\r
3323         }\r
3324 \r
3325  #endif\r
3326 }\r
3327 \r
3328 \r
3329  \r
3330 /***********************************************************************\r
3331   <<< [FileT_isFile] >>> \r
3332 ************************************************************************/\r
3333 bool  FileT_isFile( const TCHAR* path )\r
3334 {\r
3335         DWORD  r = GetFileAttributes( path );\r
3336         return  ( r & (FILE_ATTRIBUTE_DIRECTORY | 0x80000000) ) == 0;\r
3337                 // 0x80000000 \82Í\81A\83t\83@\83C\83\8b\82â\83t\83H\83\8b\83_\82ª\91\8dÝ\82µ\82È\82¢\82±\82Æ\82ð\94»\92è\82·\82é\82½\82ß\r
3338 }\r
3339 \r
3340 \r
3341  \r
3342 /***********************************************************************\r
3343   <<< [FileT_isDir] >>> \r
3344 ************************************************************************/\r
3345 bool  FileT_isDir( const TCHAR* path )\r
3346 {\r
3347         DWORD  r = GetFileAttributes( path );\r
3348         return  ( r & (FILE_ATTRIBUTE_DIRECTORY | 0x80000000) ) == FILE_ATTRIBUTE_DIRECTORY;\r
3349                 // 0x80000000 \82Í\81A\83t\83@\83C\83\8b\82â\83t\83H\83\8b\83_\82ª\91\8dÝ\82µ\82È\82¢\82±\82Æ\82ð\94»\92è\82·\82é\82½\82ß\r
3350 }\r
3351 \r
3352 \r
3353  \r
3354 /***********************************************************************\r
3355   <<< [FileT_callByNestFind] \83T\83u\83t\83H\83\8b\83_\82à\8aÜ\82ß\82Ä\8ae\83t\83@\83C\83\8b\82Ì\83p\83X\82ð\93n\82· >>> \r
3356 ************************************************************************/\r
3357 typedef struct {\r
3358         /*--- inherit from FileT_CallByNestFindData */\r
3359         void*     CallerArgument;\r
3360         TCHAR*    FullPath;  // abstruct path\r
3361         TCHAR*    StepPath;\r
3362         TCHAR*    FileName;\r
3363         DWORD     FileAttributes;\r
3364 \r
3365         /*---*/\r
3366         BitField  Flags;\r
3367         FuncType  CallbackFromNestFind;\r
3368         TCHAR     FullPathMem[4096];\r
3369 } FileT_CallByNestFindDataIn;\r
3370 \r
3371 int  FileT_callByNestFind_sub( FileT_CallByNestFindDataIn* m );\r
3372 \r
3373 \r
3374 int  FileT_callByNestFind( const TCHAR* Path, BitField Flags, void* Argument, FuncType Callback )\r
3375 {\r
3376         int  e;\r
3377         FileT_CallByNestFindDataIn  data;\r
3378 \r
3379         {\r
3380                 TCHAR*  p;\r
3381 \r
3382                 e= StrT_cpy( data.FullPathMem, sizeof(data.FullPathMem), Path ); IF(e)goto fin;\r
3383 \r
3384 \r
3385                 /* FullPathMem \82Ì\8dÅ\8cã\82É \ \82ª\96³\82¢\82È\82ç\92Ç\89Á\82·\82é */\r
3386                 p = StrT_chr( data.FullPathMem, _T('\0') );\r
3387                 p--;\r
3388                 if ( *p != _T('\\') ) {\r
3389                         p++;\r
3390                         IF( p >= data.FullPathMem + (sizeof(data.FullPathMem) / sizeof(TCHAR)) - 1 )goto err_fa;\r
3391                         *p = _T('\\');\r
3392                 }\r
3393 \r
3394 \r
3395                 /* data \82ð\8f\89\8aú\89»\82·\82é */\r
3396                 data.CallerArgument = Argument;\r
3397                 data.FullPath = data.FullPathMem;\r
3398                 data.StepPath = p + 1;\r
3399                 data.FileName = p + 1;\r
3400                 data.Flags = Flags;\r
3401                 data.CallbackFromNestFind = Callback;\r
3402         }\r
3403 \r
3404         /* \8dÄ\8bN\8cÄ\82Ñ\8fo\82µ\8aÖ\90\94\82Ö */\r
3405         e= FileT_callByNestFind_sub( &data ); IF(e)goto fin;\r
3406 \r
3407         e=0;\r
3408 fin:\r
3409         return  e;\r
3410 err_fa: e= E_FEW_ARRAY; goto fin;\r
3411 }\r
3412 \r
3413 \r
3414 int  FileT_callByNestFind_sub( FileT_CallByNestFindDataIn* m )\r
3415 {\r
3416         int  e;\r
3417         HANDLE  find;\r
3418         WIN32_FIND_DATA  data;\r
3419         TCHAR*  p;\r
3420         int  done;\r
3421 \r
3422 \r
3423         /* Path \82É\8ew\92è\82µ\82½\83t\83H\83\8b\83_\82É\91Î\82µ\82Ä\83R\81[\83\8b\83o\83b\83N\82·\82é */\r
3424         if ( m->Flags & FileT_FolderBeforeFiles ) {\r
3425                 *( m->FileName - 1 ) = _T('\0');  // m->FullPath \82Ì\8dÅ\8cã\82Ì \ \82ð\88ê\8e\9e\93I\82É\83J\83b\83g\r
3426                 *( m->FileName ) = _T('\0');  // m->FileName, m->StepPath \82ð "" \82É\82·\82é\r
3427                 m->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;\r
3428 \r
3429                 if ( m->StepPath[0] == _T('\0') ) {\r
3430                         TCHAR*  step_path = m->StepPath;\r
3431                         TCHAR*  fname     = m->FileName;\r
3432 \r
3433                         m->StepPath = _T(".");\r
3434                         m->FileName = StrT_refFName( m->FullPath );\r
3435                         e= m->CallbackFromNestFind( m ); IF(e)goto fin;\r
3436                         m->StepPath = step_path;\r
3437                         m->FileName = fname;\r
3438                 }\r
3439                 else if ( m->FileName[0] == _T('\0') ) {\r
3440                         TCHAR*  fname = m->FileName;\r
3441 \r
3442                         m->FileName = StrT_refFName( m->FullPath );\r
3443                         e= m->CallbackFromNestFind( m ); IF(e)goto fin;\r
3444                         m->FileName = fname;\r
3445                 }\r
3446                 else {\r
3447                         e= m->CallbackFromNestFind( m ); IF(e)goto fin;\r
3448                 }\r
3449                 *( m->FileName - 1 ) = _T('\\');\r
3450         }\r
3451 \r
3452 \r
3453         /* * \82ð\92Ç\89Á */\r
3454         p = m->FileName;\r
3455         IF( p >= m->FullPathMem + (sizeof(m->FullPathMem) / sizeof(TCHAR)) - 2 )goto err_fa;\r
3456         *p = _T('*');  *(p+1) = _T('\0');\r
3457 \r
3458 \r
3459         /* \83t\83@\83C\83\8b\82©\83t\83H\83\8b\83_\82ð\97ñ\8b\93\82µ\82Ü\82· */\r
3460         find = FindFirstFileEx( m->FullPathMem, FindExInfoStandard, &data,\r
3461                 FindExSearchNameMatch, NULL, 0 );\r
3462         done = ( find == INVALID_HANDLE_VALUE );\r
3463 \r
3464         while (!done)\r
3465         {\r
3466                 if ( _tcscmp( data.cFileName, _T(".") ) == 0 ||\r
3467                                  _tcscmp( data.cFileName, _T("..") ) == 0 ) {\r
3468                         done = ! FindNextFile( find, &data );\r
3469                         continue;\r
3470                 }\r
3471 \r
3472                 StrT_cpy( m->FileName,\r
3473                         sizeof(m->FullPathMem) - ( (char*)m->FileName - (char*)m->FullPathMem ),\r
3474                         data.cFileName );\r
3475                 m->FileAttributes = data.dwFileAttributes;\r
3476 \r
3477                 if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {\r
3478                         TCHAR*  prev_fname = m->FileName;\r
3479 \r
3480                         p = StrT_chr( m->FileName, _T('\0') );\r
3481 \r
3482                         IF( p >= m->FullPathMem + (sizeof(m->FullPathMem) / sizeof(TCHAR)) - 2 )goto err_fa;\r
3483                         *p = _T('\\');  *(p+1) = _T('\0');\r
3484                         m->FileName = p + 1;\r
3485 \r
3486                         e= FileT_callByNestFind_sub( m ); IF(e)goto fin;  /* \8dÄ\8bN\8cÄ\82Ñ\8fo\82µ */\r
3487 \r
3488                         m->FileName = prev_fname;\r
3489                 }\r
3490                 else {\r
3491                         e= m->CallbackFromNestFind( m ); IF(e)goto fin;\r
3492                 }\r
3493 \r
3494                 done = ! FindNextFile( find, &data );\r
3495         }\r
3496         FindClose( find );\r
3497 \r
3498 \r
3499         /* Path \82É\8ew\92è\82µ\82½\83t\83H\83\8b\83_\82É\91Î\82µ\82Ä\83R\81[\83\8b\83o\83b\83N\82·\82é */\r
3500         if ( m->Flags & FileT_FolderAfterFiles ) {\r
3501                 TCHAR*  step_path = m->StepPath;\r
3502                 TCHAR*  fname     = m->FileName;\r
3503 \r
3504                 *( m->FileName - 1 ) = _T('\0');\r
3505                 m->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;\r
3506                 if ( ( *( m->StepPath - 1 ) == _T('\0') ) && ( m->StepPath > m->FullPath ) ) {\r
3507                         m->StepPath = _T(".");\r
3508                 }\r
3509                 m->FileName = StrT_refFName( m->FullPath );\r
3510 \r
3511                 e= m->CallbackFromNestFind( m ); IF(e)goto fin;\r
3512 \r
3513                 m->StepPath = step_path;\r
3514                 m->FileName = fname;\r
3515         }\r
3516 \r
3517         e=0;\r
3518 fin:\r
3519         return  e;\r
3520 err_fa: e= E_FEW_ARRAY; goto fin;\r
3521 }\r
3522 \r
3523 \r
3524  \r
3525 /***********************************************************************\r
3526   <<< [FileT_openForRead] >>> \r
3527 ************************************************************************/\r
3528 int  FileT_openForRead( FILE** out_pFile, const TCHAR* Path )\r
3529 {\r
3530         errno_t  en;\r
3531 \r
3532         assert( Locale_isInited() );\r
3533 \r
3534         #if DEBUGTOOLS_USES\r
3535                 { int e= Debug_onOpen( Path ); if(e) return e; }\r
3536         #endif\r
3537 \r
3538         en = _tfopen_s( out_pFile, Path, _T("r")_T(fopen_ccs) );\r
3539         if ( en == ENOENT ) {\r
3540                 #ifndef UNDER_CE\r
3541                 {\r
3542                         TCHAR  cwd[512];\r
3543 \r
3544                         if ( _tgetcwd( cwd, _countof(cwd) ) == NULL ) {\r
3545                                 cwd[0] = _T('\0');\r
3546                         }\r
3547                         Error4_printf( _T("<ERROR msg=\"Not found\" path=\"%s\" current=\"%s\"/>"),\r
3548                                 Path, cwd );\r
3549                 }\r
3550                 #else\r
3551                         Error4_printf( _T("<ERROR msg=\"Not found\" path=\"%s\"/>"), Path );\r
3552                 #endif\r
3553 \r
3554                 return  E_PATH_NOT_FOUND;\r
3555         }\r
3556         if ( en == EACCES ) {\r
3557                 Error4_printf( _T("access denied \"%s\"\n"), Path );\r
3558                 return  E_ACCESS_DENIED;\r
3559         }\r
3560         IF(en)return  E_OTHERS;\r
3561 \r
3562         return  0;\r
3563 }\r
3564 \r
3565 \r
3566  \r
3567 /***********************************************************************\r
3568   <<< [FileT_openForWrite] >>> \r
3569 ************************************************************************/\r
3570 int  FileT_openForWrite( FILE** out_pFile, const TCHAR* Path,  bit_flags_fast32_t  Flags )\r
3571 {\r
3572         int      e;\r
3573         errno_t  en;\r
3574         TCHAR*   open_type;\r
3575         BOOL     b;\r
3576         int      retry_count;\r
3577 \r
3578         IF_D( ! Locale_isInited() )  return  E_NOT_INIT_GLOBAL;\r
3579 \r
3580         #if Uses_AppKey\r
3581                 e= AppKey_addNewWritableFolder( Path ); IF(e)goto fin;\r
3582         #endif\r
3583 \r
3584         if ( Flags & F_Append )\r
3585                 open_type = ( Flags & F_Unicode ? _T("a")_T(fopen_ccs) : _T("at") );\r
3586         else\r
3587                 open_type = ( Flags & F_Unicode ? _T("w")_T(fopen_ccs) : _T("wt") );\r
3588 \r
3589         #if DEBUGTOOLS_USES\r
3590                 { int e= Debug_onOpen( Path ); if(e) return e; }\r
3591         #endif\r
3592 \r
3593         for ( retry_count = 0;  ;  retry_count ++ ) {\r
3594                 en = _tfopen_s( out_pFile, Path, open_type );\r
3595                 if ( en != EACCES )  break;\r
3596                 IF ( GetFileAttributes( Path ) == FILE_ATTRIBUTE_DIRECTORY ) { goto err_gt; }\r
3597 \r
3598                 retry_count += 1;\r
3599                 if ( retry_count == 15 )  break;\r
3600                 Sleep( 1000 );\r
3601         }\r
3602         if ( en == 2 ) {  // ENOENT\r
3603                 e= FileT_mkdir( Path ); IF(e)goto fin;\r
3604                 b= RemoveDirectory( Path ); IF(!b)goto err_gt;\r
3605                 en = _tfopen_s( out_pFile, Path, open_type );\r
3606 \r
3607                 IF ( en == 2 ) {\r
3608                         _tprintf( _T("cannot open \"%s\"\n"), Path );\r
3609 \r
3610                         #ifndef UNDER_CE\r
3611                         {\r
3612                                 TCHAR  cwd[512];\r
3613 \r
3614                                 if ( _tgetcwd( cwd, _countof(cwd) ) != NULL )\r
3615                                         _tprintf( _T("current = \"%s\"\n"), cwd );\r
3616                         }\r
3617                         #endif\r
3618 \r
3619                         e = E_NOT_FOUND_SYMBOL;\r
3620                         goto fin;\r
3621                 }\r
3622         }\r
3623         IF(en)goto err;\r
3624 \r
3625         e=0;\r
3626 fin:\r
3627         return  e;\r
3628 \r
3629 err:  e = E_OTHERS;  goto fin;\r
3630 err_gt:  e = SaveWindowsLastError();  goto fin;\r
3631 }\r
3632 \r
3633 \r
3634  \r
3635 /***********************************************************************\r
3636   <<< [FileT_close] >>> \r
3637 ************************************************************************/\r
3638 int  FileT_close( FILE* File, int e )\r
3639 {\r
3640         if ( File != NULL ) {\r
3641                 int r = fclose( File );\r
3642                 IF(r&&!e)e=E_ERRNO;\r
3643         }\r
3644         return e;\r
3645 }\r
3646 \r
3647 \r
3648 \r
3649  \r
3650 /***********************************************************************\r
3651   <<< [FileT_closeAndNULL] >>> \r
3652 ************************************************************************/\r
3653 errnum_t  FileT_closeAndNULL( FILE** in_out_File, errnum_t e )\r
3654 {\r
3655         FILE*  file = *in_out_File;\r
3656 \r
3657         if ( file != NULL ) {\r
3658                 int  r = fclose( file );\r
3659                 IF ( r && e == 0 ) { e = E_ERRNO; }\r
3660                 *in_out_File = NULL;\r
3661         }\r
3662 \r
3663         return  e;\r
3664 }\r
3665 \r
3666 \r
3667 \r
3668  \r
3669 /***********************************************************************\r
3670   <<< [FileT_readAll] >>> \r
3671 ************************************************************************/\r
3672 #ifdef  IsTest_FileT_readAll\r
3673         #define _CV(x)  CoverageLogClass_output( x, _T("FileT_readAll") )\r
3674 #else\r
3675         #define _CV(x)\r
3676 #endif\r
3677 \r
3678 errnum_t  FileT_readAll( FILE* File, TCHAR** out_Text, size_t* out_TextLength )\r
3679 {\r
3680 #ifdef  IsTest_FileT_readAll\r
3681         enum { text_max_size_first = 0x10 };\r
3682 #else\r
3683         enum { text_max_size_first = 0xFF00 };\r
3684 #endif\r
3685         errnum_t  e;\r
3686         TCHAR*    text = NULL;\r
3687         TCHAR*    text_over = (TCHAR*) DUMMY_INITIAL_VALUE;\r
3688         size_t    text_max_size = text_max_size_first;\r
3689         TCHAR*    text_max_over;\r
3690 \r
3691 \r
3692         text = (TCHAR*) malloc( text_max_size ); IF( text == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
3693         text_over = text;\r
3694         text_max_over = (TCHAR*)( (uint8_t*) text + text_max_size );\r
3695 \r
3696         text[0] = _T('\0');  /* for empty file */\r
3697 \r
3698         for (;;) {\r
3699                 _fgetts( text_over, text_max_over - text_over, File );\r
3700 \r
3701                 if ( *text_over == _T('\0') ) {  /* End of file. If space line, *text_over == _T('\n').  */\r
3702                         _CV(1);\r
3703                         ASSERT_R( feof( File ), e=E_OTHERS; goto fin );\r
3704                         break;\r
3705                 }\r
3706                 text_over = StrT_chr( text_over, _T('\0') );\r
3707                 if ( feof( File ) ) { break; }\r
3708 \r
3709                 if ( (uint8_t*) text_over - (uint8_t*) text == (int)( text_max_size - sizeof(TCHAR) ) ) {\r
3710                                 /* if full in text */\r
3711                         TCHAR*  new_text;\r
3712                         size_t  old_text_max_size = text_max_size;\r
3713 \r
3714                         #ifdef  IsTest_FileT_readAll\r
3715                                 EmptyHeapMemoryEmulation( _T("T_FileT_readAll_FewMemory"), 1 );\r
3716                         #endif\r
3717 \r
3718                         text_max_size *= 4;\r
3719                         new_text = (TCHAR*) realloc( text, text_max_size );\r
3720                                 IF( new_text == NULL ) { e=E_FEW_MEMORY; _CV(2); goto fin; }\r
3721                         text = new_text;\r
3722                         text_over = (TCHAR*)( (uint8_t*) new_text + old_text_max_size - sizeof(TCHAR) );\r
3723                         text_max_over = (TCHAR*)( (uint8_t*) text + text_max_size );\r
3724                 }\r
3725                 else {\r
3726                         _CV(3);\r
3727                 }\r
3728         }\r
3729 \r
3730         e=0;\r
3731 fin:\r
3732         if ( e ) {\r
3733                 if ( text != NULL ) { _CV(4); free( text ); }\r
3734         }\r
3735         else {\r
3736                 *out_Text = text;\r
3737                 if ( out_TextLength != NULL ) { *out_TextLength = text_over - text; }\r
3738         }\r
3739         return  e;\r
3740 }\r
3741 #undef _CV\r
3742 \r
3743 \r
3744  \r
3745 /***********************************************************************\r
3746   <<< [FileT_writePart] >>> \r
3747 ************************************************************************/\r
3748 errnum_t  FileT_writePart( FILE* File, const TCHAR* Start, TCHAR* Over )\r
3749 {\r
3750         errnum_t  e;\r
3751         TCHAR     back_char;\r
3752         int       r;\r
3753 \r
3754         back_char = *Over;\r
3755 \r
3756         IF ( Start > Over ) { e=E_OTHERS; goto fin; }\r
3757 \r
3758         *Over = _T('\0');\r
3759         r= _ftprintf_s( File, _T("%s"), Start ); IF(r<0){ e=E_ERRNO; goto fin; }\r
3760 \r
3761         e=0;\r
3762 fin:\r
3763         *Over = back_char;\r
3764         return  e;\r
3765 }\r
3766 \r
3767 \r
3768  \r
3769 /***********************************************************************\r
3770   <<< [FileT_mkdir] >>> \r
3771 ************************************************************************/\r
3772 int  FileT_mkdir( const TCHAR* Path )\r
3773 {\r
3774         int    e;\r
3775         DWORD  r;\r
3776         TCHAR* p = (TCHAR*) DUMMY_INITIAL_VALUE;\r
3777         BOOL   b;\r
3778         int    n_folder = 0;\r
3779         TCHAR  path2[MAX_PATH];\r
3780 \r
3781 \r
3782         e= StrT_getFullPath( path2, sizeof(path2), Path, NULL ); IF(e)goto fin;\r
3783         #if Uses_AppKey\r
3784                 e= AppKey_addNewWritableFolder( path2 ); IF(e)goto fin;\r
3785         #endif\r
3786 \r
3787 \r
3788         //=== \91\8dÝ\82·\82é\83t\83H\83\8b\83_\82ð\92T\82·\r
3789         for (;;) {\r
3790                 r = GetFileAttributes( path2 );\r
3791                 if ( r != (DWORD)-1 ) break;  // "C:" \82à\83t\83H\83\8b\83_\82Æ\94»\92è\82³\82ê\82é\r
3792 \r
3793                 p = StrT_refFName( path2 ) - 1;  // \90â\91Î\83p\83X\82È\82Ì\82Å\95K\82¸ *p=='\\'\r
3794                 *p = _T('\0');\r
3795                 n_folder ++;\r
3796         }\r
3797         IF ( ! (r & FILE_ATTRIBUTE_DIRECTORY) ) goto err;  // \83t\83@\83C\83\8b\82È\82ç\83G\83\89\81[\r
3798 \r
3799 \r
3800         //=== \83t\83H\83\8b\83_\82ð\8dì\90¬\82·\82é\r
3801         for ( ;  n_folder > 0;  n_folder -- ) {\r
3802                 *p = _T('\\');\r
3803                 b= CreateDirectory( path2, NULL ); IF(!b)goto err;\r
3804                 p = StrT_chr( p, _T('\0') );\r
3805         }\r
3806 \r
3807         e=0;\r
3808 fin:\r
3809         return  e;\r
3810 \r
3811 err:  e = E_OTHERS;  goto fin;\r
3812 }\r
3813 \r
3814 \r
3815 \r
3816  \r
3817 /***********************************************************************\r
3818   <<< [FileT_copy] >>> \r
3819 ************************************************************************/\r
3820 int  FileT_copy_sub( FileT_CallByNestFindData* m );\r
3821 \r
3822 int  FileT_copy( const TCHAR* SrcPath, const TCHAR* DstPath )\r
3823 {\r
3824         const TCHAR*  p_last;\r
3825         int    e;\r
3826         BOOL   b;\r
3827         TCHAR  path[MAX_PATH*4];\r
3828 \r
3829 \r
3830         #if Uses_AppKey\r
3831                 e= AppKey_addNewWritableFolder( DstPath ); IF(e)goto fin;\r
3832         #endif\r
3833 \r
3834         p_last = StrT_chr( SrcPath, _T('\0') );\r
3835         IF_D( p_last <= SrcPath + 1 )goto err_ni;\r
3836 \r
3837 \r
3838         //=== \83t\83H\83\8b\83_\82ð\83R\83s\81[\82·\82é\r
3839         if ( *(p_last - 1) == _T('*') ) {\r
3840                 IF_D( *(p_last - 2) != _T('\\') ) goto err_ni;\r
3841 \r
3842                 e= StrT_getParentFullPath( path, sizeof(path), SrcPath, NULL ); IF(e)goto fin;\r
3843                 IF_D( ! FileT_isDir( path ) )goto err_nf;\r
3844 \r
3845                 e= FileT_callByNestFind( path, FileT_FolderBeforeFiles, (void*) DstPath, (FuncType) FileT_copy_sub );\r
3846                 IF(e)goto fin;\r
3847         }\r
3848 \r
3849 \r
3850         //=== \83t\83@\83C\83\8b\82ð\83R\83s\81[\82·\82é\r
3851         else {\r
3852                 IF_D( _tcschr( SrcPath, _T('*') ) != NULL )goto err_ni;\r
3853                 IF_D( ! FileT_isFile( SrcPath ) ) goto err_nf;\r
3854 \r
3855                 b= CopyFile( SrcPath, DstPath, FALSE );\r
3856                 if (!b) {\r
3857                         if ( FileT_isDir( DstPath ) ) {\r
3858                                 e= stprintf_r( path, sizeof(path), _T("%s\\%s"), DstPath, StrT_refFName( SrcPath ) ); IF(e)goto fin;\r
3859                                 b= CopyFile( SrcPath, path, FALSE ); IF(!b)goto err_gt;\r
3860                         }\r
3861                         else {\r
3862                                 int  ee;\r
3863 \r
3864                                 p_last = StrT_chr( DstPath, _T('\0') ) - 1;\r
3865                                 IF_D( p_last < DstPath )goto err;\r
3866                                 if ( *p_last == _T('\\') ) {\r
3867                                         ee= FileT_mkdir( DstPath ); IF(ee)goto fin;\r
3868                                         e= stprintf_r( path, sizeof(path), _T("%s%s"), DstPath, StrT_refFName( SrcPath ) ); IF(e)goto fin;\r
3869                                         b= CopyFile( SrcPath, path, FALSE ); IF(!b)goto err_gt;\r
3870                                 }\r
3871                                 else {\r
3872                                         e = E_ACCESS_DENIED;\r
3873                                         ee= StrT_getParentFullPath( path, sizeof(path), DstPath, NULL ); IF(ee)goto fin;\r
3874                                         ee= FileT_mkdir( path ); IF(ee)goto fin;\r
3875                                         b= CopyFile( SrcPath, DstPath, FALSE ); IF(!b)goto err_gt;\r
3876                                 }\r
3877                         }\r
3878                 }\r
3879         }\r
3880 \r
3881         e=0;\r
3882 fin:\r
3883         return  e;\r
3884 \r
3885 err_ni:  e = E_NOT_IMPLEMENT_YET;  goto fin;\r
3886 err_nf:  e = E_PATH_NOT_FOUND;  goto fin;\r
3887 err_gt:  e = SaveWindowsLastError();  goto fin;\r
3888 err:  e = E_OTHERS;  goto fin;\r
3889 }\r
3890 \r
3891 \r
3892 int  FileT_copy_sub( FileT_CallByNestFindData* m )\r
3893 {\r
3894         const  TCHAR*  DstPath = (const TCHAR*) m->CallerArgument;\r
3895         int    e;\r
3896         BOOL   b;\r
3897         TCHAR  path[MAX_PATH*4];\r
3898 \r
3899         e= stprintf_r( path, sizeof(path), _T("%s\\%s"), DstPath, m->StepPath ); IF(e)goto fin;\r
3900 \r
3901         if ( m->FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {\r
3902                 if ( ! FileT_isDir( path ) )\r
3903                         { b= CreateDirectory( path, NULL ); IF(!b)goto err_gt; }\r
3904         }\r
3905         else {\r
3906                 b= CopyFile( m->FullPath, path, FALSE ); IF(!b)goto err_gt;\r
3907         }\r
3908 \r
3909         e=0;\r
3910 fin:\r
3911         return  e;\r
3912 \r
3913 err_gt:  e = SaveWindowsLastError();  goto fin;\r
3914 }\r
3915 \r
3916 \r
3917 \r
3918  \r
3919 /***********************************************************************\r
3920   <<< [FileT_del] >>> \r
3921 ************************************************************************/\r
3922 int  FileT_del_sub( FileT_CallByNestFindData* m );\r
3923 \r
3924 int  FileT_del( const TCHAR* Path )\r
3925 {\r
3926         int    e;\r
3927         DWORD  r;\r
3928         TCHAR  abs_path[MAX_PATH];\r
3929 \r
3930         e= StrT_getFullPath( abs_path, sizeof(abs_path), Path, NULL ); IF(e)goto fin;\r
3931         #if Uses_AppKey\r
3932                 e= AppKey_addNewWritableFolder( abs_path ); IF(e)goto fin;\r
3933         #endif\r
3934 \r
3935         r= GetFileAttributes( Path );\r
3936         if ( r != (DWORD)-1 ) {\r
3937                 if ( r & FILE_ATTRIBUTE_DIRECTORY ) {\r
3938                         e= FileT_callByNestFind( Path, FileT_FolderAfterFiles, NULL, (FuncType) FileT_del_sub );\r
3939                 }\r
3940                 else {\r
3941                         BOOL  b= DeleteFile( Path ); IF(!b)goto err_gt;\r
3942                 }\r
3943         }\r
3944         IF_D( FileT_isExist( Path ) )goto err_ad;\r
3945 \r
3946         e=0;\r
3947 fin:\r
3948         return  e;\r
3949 \r
3950 err_gt:  e = SaveWindowsLastError();  goto fin;\r
3951 err_ad:  e = E_ACCESS_DENIED;  goto fin;\r
3952 }\r
3953 \r
3954 \r
3955 int  FileT_del_sub( FileT_CallByNestFindData* m )\r
3956 {\r
3957         int   e;\r
3958         BOOL  b;\r
3959 \r
3960         if ( m->FileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {\r
3961                 b= RemoveDirectory( m->FullPath ); IF(!b)goto err_gt;\r
3962         }\r
3963         else {\r
3964                 b= DeleteFile( m->FullPath ); IF(!b)goto err_gt;\r
3965         }\r
3966 \r
3967         e=0;\r
3968 fin:\r
3969         return  e;\r
3970 \r
3971 err_gt:  e = SaveWindowsLastError();  goto fin;\r
3972 }\r
3973  \r
3974 /***********************************************************************\r
3975   <<< [FileT_writeSizedStruct_WinAPI] >>> \r
3976 ************************************************************************/\r
3977 int  FileT_writeSizedStruct_WinAPI( HANDLE* Stream, SizedStruct* OutputSizedStruct )\r
3978 {\r
3979         DWORD  wrote_size;\r
3980         BOOL   r;\r
3981         int    e;\r
3982 \r
3983         r= WriteFile( Stream, &OutputSizedStruct->ThisStructSize,\r
3984                 sizeof(OutputSizedStruct->ThisStructSize), &wrote_size, NULL );\r
3985         IF(!r) goto err_gt;\r
3986 \r
3987         r= WriteFile( Stream, &OutputSizedStruct->OthersData,\r
3988                 OutputSizedStruct->ThisStructSize - sizeof(OutputSizedStruct->ThisStructSize),\r
3989                 &wrote_size, NULL );\r
3990         IF(!r) goto err_gt;\r
3991         e=0;\r
3992 fin:\r
3993         return  0;\r
3994 \r
3995 err_gt:  e = SaveWindowsLastError();  goto fin;\r
3996 }\r
3997 \r
3998  \r
3999 /***********************************************************************\r
4000   <<< [FileT_readSizedStruct_WinAPI] >>> \r
4001 ************************************************************************/\r
4002 int  FileT_readSizedStruct_WinAPI( HANDLE* Stream, void** out_SizedStruct )\r
4003 {\r
4004         int    e;\r
4005         DWORD  read_size;\r
4006         DWORD  data_size;\r
4007         void*  out = NULL;\r
4008         BOOL   b;\r
4009 \r
4010         b= ReadFile( Stream, &data_size, sizeof(data_size), &read_size, NULL ); IF(!b) goto err_gt;\r
4011         IF( data_size & 0xC0000000 ) goto err_fm;\r
4012 \r
4013         out = malloc( data_size ); IF( out == NULL ) goto err_fm;\r
4014         *(size_t*) out = data_size;\r
4015 \r
4016         b= ReadFile( Stream, (size_t*) out + 1, data_size - sizeof(size_t), &read_size, NULL ); IF(!b) goto err_gt;\r
4017 \r
4018         *out_SizedStruct = out;\r
4019 \r
4020         e=0;\r
4021 fin:\r
4022         return  e;\r
4023 \r
4024 err_gt:  e = SaveWindowsLastError();  goto rollback;\r
4025 err_fm:  e = E_FEW_MEMORY;  goto rollback;\r
4026 rollback:\r
4027         if ( out != NULL )  free( out );\r
4028         goto fin;\r
4029 }\r
4030 \r
4031 \r
4032  \r
4033 /***********************************************************************\r
4034 * Implement: FileT_readUnicodeFileBOM\r
4035 ************************************************************************/\r
4036 errnum_t  FileT_readUnicodeFileBOM( const TCHAR* Path, FileFormatEnum* out_Format )\r
4037 {\r
4038         errnum_t  e;\r
4039         HANDLE    file = INVALID_HANDLE_VALUE;\r
4040         unsigned char  data[4];\r
4041         DWORD     read_size;\r
4042         BOOL      b;\r
4043 \r
4044         if ( ! FileT_isExist( Path ) ) {\r
4045                 *out_Format = FILE_FORMAT_NOT_EXIST;\r
4046         }\r
4047         else {\r
4048                 file = CreateFile( Path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,\r
4049                         FILE_ATTRIBUTE_NORMAL, 0 );\r
4050                         IF( file == INVALID_HANDLE_VALUE ) goto err_gt;\r
4051 \r
4052                 data[0] = '\0';\r
4053                 b= ReadFile( file, data, 3, &read_size, NULL ); IF(!b)goto err;\r
4054                 if ( read_size < 2 ) {\r
4055                         *out_Format = FILE_FORMAT_NO_BOM;\r
4056                 }\r
4057                 else if ( ( data[0] == 0xFF ) && ( data[1] == 0xFE ) ) {\r
4058                         *out_Format = FILE_FORMAT_UNICODE;\r
4059                 }\r
4060                 else if ( ( read_size >= 3 ) &&\r
4061                         ( data[0] == 0xEF ) && ( data[1] == 0xBB ) && ( data[2] == 0xBF ) ) {\r
4062 \r
4063                         *out_Format = FILE_FORMAT_UTF_8;\r
4064                 }\r
4065                 else {\r
4066                         *out_Format = FILE_FORMAT_NO_BOM;\r
4067                 }\r
4068         }\r
4069 \r
4070         e=0;\r
4071 fin:\r
4072         if ( file != INVALID_HANDLE_VALUE )  { b= CloseHandle( file ); IF(!b&&!e) e = E_OTHERS; }\r
4073         return  e;\r
4074 \r
4075 err_gt:  e = SaveWindowsLastError();  goto fin;\r
4076 err:     e = E_OTHERS;          goto fin;\r
4077 }\r
4078 \r
4079 \r
4080  \r
4081 /***********************************************************************\r
4082 * Implement: FileT_cutFFFE\r
4083 ************************************************************************/\r
4084 errnum_t  FileT_cutFFFE( const TCHAR*  in_InputPath,  const TCHAR*  in_OutputPath,  bool  in_IsAppend )\r
4085 {\r
4086         errnum_t  e;\r
4087         HANDLE    reading_file = INVALID_HANDLE_VALUE;\r
4088         HANDLE    writing_file = INVALID_HANDLE_VALUE;\r
4089         wchar_t   buffer[4096];\r
4090         uint8_t*  buffer8 = (uint8_t*) buffer;\r
4091         wchar_t   a_character;\r
4092         uint8_t   a_character8;\r
4093         int       index_of_BOM;\r
4094         DWORD     read_size;\r
4095         DWORD     writing_size;\r
4096         DWORD     wrote_size;\r
4097         DWORD     reading_index;\r
4098         DWORD     reading_index_over;\r
4099         DWORD     writing_index;\r
4100         DWORD     creation;\r
4101         BOOL      b;\r
4102 \r
4103         FileFormatEnum  format;\r
4104 \r
4105         e= FileT_readUnicodeFileBOM( in_InputPath,  /*Set*/ &format ); IF(e){goto fin;}\r
4106 \r
4107         if ( ! in_IsAppend ) {\r
4108                 creation = CREATE_ALWAYS;\r
4109         } else {\r
4110                 creation = OPEN_ALWAYS;\r
4111         }\r
4112 \r
4113         reading_file = CreateFile( in_InputPath,  GENERIC_READ,  FILE_SHARE_READ,  NULL,  OPEN_EXISTING,\r
4114                 FILE_ATTRIBUTE_NORMAL, 0 );\r
4115                 IF( reading_file == INVALID_HANDLE_VALUE ) { e=E_GET_LAST_ERROR; goto fin; }\r
4116 \r
4117         writing_file = CreateFile( in_OutputPath,  GENERIC_WRITE,  0,  NULL,  creation,\r
4118                 FILE_ATTRIBUTE_NORMAL, 0 );\r
4119                 IF ( writing_file == INVALID_HANDLE_VALUE ) { e=E_GET_LAST_ERROR; goto fin; }\r
4120 \r
4121         if ( in_IsAppend ) {\r
4122                 SetFilePointer( writing_file,  0,  NULL,  FILE_END );\r
4123         }\r
4124 \r
4125 \r
4126         for (;;) {\r
4127 \r
4128                 b= ReadFile( reading_file,  buffer,  sizeof( buffer ),  &read_size,  NULL );\r
4129                         IF(!b){ e=SaveWindowsLastError(); goto fin; }\r
4130                 if ( read_size == 0 )\r
4131                         { break; }\r
4132 \r
4133                 if ( format == FILE_FORMAT_UNICODE ) {\r
4134                         writing_index = 0;\r
4135                         reading_index_over = read_size / sizeof( buffer[0] );\r
4136                         for ( reading_index = 0;  reading_index < reading_index_over;  reading_index += 1 ) {\r
4137 \r
4138                                 a_character = buffer[ reading_index ];\r
4139 \r
4140                                 if ( a_character != 0xFEFF ) {  /* FEFF = BOM character */\r
4141 \r
4142                                         buffer[ writing_index ] = a_character;\r
4143                                         writing_index += 1;\r
4144                                 }\r
4145                         }\r
4146                         writing_size = writing_index * sizeof( buffer[0] );\r
4147                 }\r
4148                 else if ( format == FILE_FORMAT_UTF_8 ) {\r
4149                         writing_index = 0;\r
4150                         index_of_BOM = 0;\r
4151                         reading_index_over = read_size / sizeof( buffer8[0] );\r
4152                         for ( reading_index = 0;  reading_index < reading_index_over;  reading_index += 1 ) {\r
4153 \r
4154                                 a_character8 = buffer8[ reading_index ];\r
4155 \r
4156                                 if ( a_character8 == 0xEF ) {\r
4157                                         if ( index_of_BOM >= 1 ) {\r
4158                                                 buffer8[ writing_index ] = 0xEF;\r
4159                                                 writing_index += 1;\r
4160                                                 if ( index_of_BOM >= 2 ) {\r
4161                                                         buffer8[ writing_index ] = 0xBB;\r
4162                                                         writing_index += 1;\r
4163                                                 }\r
4164                                         }\r
4165                                         index_of_BOM = 1;\r
4166                                 }\r
4167                                 else if ( a_character8 == 0xBB  &&  index_of_BOM == 1 ) {\r
4168                                         index_of_BOM = 2;\r
4169                                 }\r
4170                                 else if ( a_character8 == 0xBF  &&  index_of_BOM == 2 ) {\r
4171 \r
4172                                         /* Skip BOM */\r
4173                                         index_of_BOM = 0;\r
4174                                 }\r
4175                                 else {\r
4176                                         if ( index_of_BOM >= 1 ) {\r
4177                                                 buffer8[ writing_index ] = 0xEF;\r
4178                                                 writing_index += 1;\r
4179                                                 if ( index_of_BOM >= 2 ) {\r
4180                                                         buffer8[ writing_index ] = 0xBB;\r
4181                                                         writing_index += 1;\r
4182                                                 }\r
4183                                         }\r
4184 \r
4185                                         buffer8[ writing_index ] = a_character8;\r
4186                                         writing_index += 1;\r
4187 \r
4188                                         index_of_BOM = 0;\r
4189                                 }\r
4190                         }\r
4191                         writing_size = writing_index * sizeof( buffer8[0] );\r
4192                 }\r
4193                 else {\r
4194                         writing_size = read_size;\r
4195                 }\r
4196 \r
4197                 b= WriteFile( writing_file,  buffer,  writing_size,  &wrote_size,  NULL );\r
4198                         IF(!b) { e=E_GET_LAST_ERROR; goto fin; }\r
4199         }\r
4200 \r
4201         e=0;\r
4202 fin:\r
4203         e= CloseHandleInFin( writing_file, e );\r
4204         e= CloseHandleInFin( reading_file, e );\r
4205         return  e;\r
4206 }\r
4207 \r
4208 \r
4209  \r
4210 /***********************************************************************\r
4211   <<< [ParseXML2_StatusClass_getAttribute] >>>\r
4212 ************************************************************************/\r
4213 errnum_t  ParseXML2_StatusClass_getAttribute( ParseXML2_StatusClass* self,\r
4214         const TCHAR* AttributeName, TCHAR** out_AttribyteValue )\r
4215 {\r
4216         TCHAR**  attr;\r
4217 \r
4218         for ( attr = (TCHAR**) self->u.OnStartElement.Attributes;  *attr != NULL;  attr += 2 ) {\r
4219                 if ( _tcsicmp( *attr, AttributeName ) == 0 ) {\r
4220                         *out_AttribyteValue = *( attr + 1 );\r
4221                         return  0;\r
4222                 }\r
4223         }\r
4224         *out_AttribyteValue = NULL;\r
4225         return  0;\r
4226 }\r
4227 \r
4228 \r
4229  \r
4230 /***********************************************************************\r
4231   <<< [ParseXML2_StatusClass_mallocCopyText] >>>\r
4232 ************************************************************************/\r
4233 errnum_t  ParseXML2_StatusClass_mallocCopyText( ParseXML2_StatusClass* self,\r
4234         TCHAR** out_Text )\r
4235 {\r
4236         return  MallocAndCopyStringByLength( out_Text,\r
4237                 self->u.OnText.Text,  self->u.OnText.TextLength );\r
4238 }\r
4239 \r
4240 \r
4241  \r
4242 /***********************************************************************\r
4243   <<< [ParseXML2] >>>\r
4244 ************************************************************************/\r
4245 \r
4246 /*[ParseXML2_WorkClass]*/\r
4247 typedef struct _ParseXML2_WorkClass  ParseXML2_WorkClass;\r
4248 struct _ParseXML2_WorkClass {\r
4249         ParseXML2_StatusClass   Status;\r
4250         ParseXML2_CallbackType  OnStartElement;\r
4251         ParseXML2_CallbackType  OnEndElement;\r
4252         ParseXML2_CallbackType  OnText;\r
4253         Set2      XPath;         /* Array of TCHAR */\r
4254         Set2      XPathLengths;  /* Array of int. Element is TCHAR count. Array count is Status.Depth */\r
4255         StrFile   TextBuffer;\r
4256         int       TextStartLineNum;  /* 0 = no text */\r
4257         errnum_t  e;\r
4258 };\r
4259 \r
4260 /*[BOM]*/\r
4261 enum { BOM = 0xFEFF };\r
4262 \r
4263 \r
4264 static errnum_t  ParseXML2_makeXML_Declare_Sub( XML_Parser parser, ParseXML2_WorkClass* work,\r
4265         const TCHAR* XML_Path, TCHAR* line, bool* is_xml_declare );\r
4266 static void  Expat_printfToError4( XML_Parser parser, const TCHAR* XML_Path );\r
4267 static void  ParseXML2_onStartElement( void* UserData, const XML_Char* Name, const XML_Char** Atts );\r
4268 static void  ParseXML2_onEndElement( void* UserData, const XML_Char* name );\r
4269 static void  ParseXML2_onText( void* UserData, const XML_Char* Text, int TextLength );\r
4270 static void  ParseXML2_callOnText( ParseXML2_WorkClass* work );\r
4271 \r
4272 \r
4273 errnum_t  ParseXML2( const TCHAR* XML_Path, ParseXML2_ConfigClass* in_out_Config )\r
4274 {\r
4275         errnum_t    e;\r
4276         FILE*       file = NULL;\r
4277         XML_Parser  parser = (XML_Parser) DUMMY_INITIAL_VALUE;\r
4278         bool        is_parser = false;\r
4279         int         is_EOF;\r
4280         wchar_t     bom[1] = { BOM };\r
4281         bool        is_xml_declare = false;  /* <?xml ... ?> */\r
4282         enum XML_Status  xs;\r
4283         ParseXML2_ConfigClass*  config = in_out_Config;\r
4284         ParseXML2_ConfigClass   default_config;\r
4285         ParseXML2_WorkClass     work_x;\r
4286         ParseXML2_WorkClass*    work = &work_x;\r
4287         TCHAR    line[4096];\r
4288 \r
4289         Set2_initConst( &work->XPath );\r
4290         Set2_initConst( &work->XPathLengths );\r
4291         StrFile_initConst( &work->TextBuffer );\r
4292 \r
4293 \r
4294         /* Set "config" */\r
4295         if ( config == NULL )  { config = &default_config; }\r
4296         if ( ! ( config->Flags & F_ParseXML2_Delegate ) )        { config->Delegate = NULL; }\r
4297         if ( ! ( config->Flags & F_ParseXML2_OnStartElement ) )  { config->OnStartElement = DefaultFunction; }\r
4298         if ( ! ( config->Flags & F_ParseXML2_OnEndElement ) )    { config->OnEndElement = DefaultFunction; }\r
4299         if ( ! ( config->Flags & F_ParseXML2_OnText ) )          { config->OnText = DefaultFunction; }\r
4300 \r
4301         /* Set "work" */\r
4302         work->Status.Delegate = config->Delegate;\r
4303         work->Status.LineNum = 0;\r
4304         work->Status.Depth = -1;\r
4305         work->Status.PreviousCallbackType = 0;\r
4306         work->Status.TagName = NULL;\r
4307         work->Status.u.OnStartElement.Attributes = NULL;\r
4308         work->OnStartElement = config->OnStartElement;\r
4309         work->OnEndElement   = config->OnEndElement;\r
4310         work->OnText         = config->OnText;\r
4311         work->e = 0;\r
4312 \r
4313         /* Set "work->XPath", "work->XPathLengths" */\r
4314         {\r
4315                 TCHAR*  xpath;\r
4316 \r
4317                 e= Set2_init( &work->XPath, MAX_PATH * sizeof(TCHAR) ); IF(e)goto fin;\r
4318                 e= Set2_init( &work->XPathLengths, 10 * sizeof(int) ); IF(e)goto fin;\r
4319                 xpath = (TCHAR*) work->XPath.First;\r
4320 \r
4321                 xpath[0] = _T('/');\r
4322                 xpath[1] = _T('\0');\r
4323         }\r
4324 \r
4325         /* Set "work->TextBuffer" */\r
4326         e= StrFile_init_toHeap( &work->TextBuffer, 0 );\r
4327         work->TextStartLineNum = 0;\r
4328 \r
4329         /* Set "parser" */\r
4330         parser = XML_ParserCreate( NULL );\r
4331         is_parser = true;\r
4332         XML_SetUserData( parser, work );\r
4333         XML_SetElementHandler( parser, ParseXML2_onStartElement, ParseXML2_onEndElement );\r
4334         XML_SetCharacterDataHandler( parser, ParseXML2_onText );\r
4335 \r
4336         /* Parse BOM */\r
4337         xs= XML_Parse( parser, (char*)bom, sizeof(bom), 0 );\r
4338                 IF( xs == XML_STATUS_ERROR ) goto err_ex;\r
4339 \r
4340 \r
4341         /* Loop of lines of XML file */\r
4342         e= FileT_openForRead( &file, XML_Path ); IF(e)goto fin;\r
4343         for (;;) {\r
4344                 line[0] = _T('\0');\r
4345                 _fgetts( line, _countof(line), file );\r
4346                 is_EOF = feof( file );\r
4347                 work->Status.LineNum += 1;\r
4348 \r
4349                 /* _fgetts \82ª UTF-16 \82É\95\8e\9a\97ñ\82ð\93\9d\88ê\82µ\81A\82»\82ê\82ð XML_Parser \82É\93n\82·\82½\82ß\81A*/\r
4350                 /*  <?xml encoding="UTF-16" ?> \82É\95Ï\8dX\82·\82é */\r
4351                 if ( ! is_xml_declare ) {\r
4352                         e= ParseXML2_makeXML_Declare_Sub( parser, work, XML_Path, line, &is_xml_declare );\r
4353                                 IF(e)goto fin;\r
4354                 }\r
4355 \r
4356                 /* Parse XML */\r
4357                 xs= XML_Parse( parser, (char*)line, _tcslen( line ) * sizeof(TCHAR), is_EOF );\r
4358                         IF( xs == XML_STATUS_ERROR ) goto err_ex;\r
4359                         IF( work->e != 0 )  { e = work->e;  goto fin; }\r
4360                 if ( is_EOF )  { break; }\r
4361         }\r
4362         e=0;\r
4363 fin:\r
4364         if ( is_parser )  { XML_ParserFree( parser ); }\r
4365         e= FileT_close( file, e );\r
4366         e= StrFile_finish( &work->TextBuffer, e );\r
4367         e= Set2_finish( &work->XPath, e );\r
4368         e= Set2_finish( &work->XPathLengths, e );\r
4369         return  e;\r
4370 \r
4371 err_ex:  Expat_printfToError4( parser, XML_Path );  e= E_XML_PARSER;  goto fin;\r
4372 }\r
4373 \r
4374 \r
4375 /*[ParseXML2_makeXML_Declare_Sub]*/\r
4376 static errnum_t  ParseXML2_makeXML_Declare_Sub( XML_Parser parser, ParseXML2_WorkClass* work,\r
4377         const TCHAR* XML_Path, TCHAR* line, bool* is_xml_declare )\r
4378 {\r
4379         errnum_t  e;\r
4380         TCHAR*    p;\r
4381         TCHAR*    str = NULL;\r
4382         enum XML_Status  xs;\r
4383 \r
4384         UNREFERENCED_VARIABLE( work );\r
4385 \r
4386         if ( _tcschr( line, _T('<') ) > 0 ) {\r
4387                 if ( _tcsstr( line, _T("<?") ) > 0 ) {\r
4388                         bool  is_replaced = false;\r
4389 \r
4390                         {\r
4391                                 static const TCHAR*  enc_sjis       = _T("encoding=\"Shift_JIS\"");\r
4392                                 static const TCHAR*  enc_sjis_utf16 = _T("encoding=\"UTF-16\"   ");\r
4393 \r
4394                                 p = _tcsstr( line, enc_sjis );\r
4395                                 if ( p != NULL ) {\r
4396                                         memcpy( p, enc_sjis_utf16, _tcslen( enc_sjis_utf16 ) * sizeof(TCHAR) );\r
4397                                         is_replaced = true;\r
4398                                 }\r
4399                         }\r
4400                         if ( ! is_replaced ) {\r
4401                                 static const TCHAR*  enc_utf8       = _T("encoding=\"UTF-8\"");\r
4402                                 static const TCHAR*  enc_utf8_utf16 = _T("encoding=\"UTF-16\"");\r
4403                                 size_t  str_size;\r
4404 \r
4405                                 p = _tcsstr( line, enc_utf8 );\r
4406                                 if ( p != NULL ) {\r
4407                                         str_size = ( _tcslen( line ) + 2 ) * sizeof(TCHAR);\r
4408                                         str = (TCHAR*) malloc( str_size ); IF(str==NULL) goto err_fm;\r
4409 \r
4410                                         e= StrT_replace( str,  str_size,  line, enc_utf8,  enc_utf8_utf16, 0 );\r
4411                                                 IF(e)goto fin;\r
4412 \r
4413                                         xs= XML_Parse( parser, (char*)str, _tcslen( str ) * sizeof(TCHAR), 0 );\r
4414                                                 IF( xs == XML_STATUS_ERROR ) goto err_ex;\r
4415 \r
4416                                         line[0] = _T('\0');\r
4417                                         *is_xml_declare = true;\r
4418                                         e=0;\r
4419                                         goto fin;\r
4420                                 }\r
4421                         }\r
4422                 }\r
4423                 else {\r
4424                         static const TCHAR*  xml_declare = _T("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n");\r
4425 \r
4426                         XML_Parse( parser, (char*)xml_declare, _tcslen( xml_declare ) * sizeof(TCHAR), 0 );\r
4427                         *is_xml_declare = true;\r
4428                         e=0;\r
4429                         goto fin;\r
4430                 }\r
4431         }\r
4432         if ( _tcsstr( line, _T("?>") ) != NULL ) {\r
4433                 *is_xml_declare = true;\r
4434         }\r
4435 \r
4436         e=0;\r
4437 fin:\r
4438         if ( str != NULL )  { free( str ); }\r
4439         return  e;\r
4440 \r
4441 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
4442 err_ex:  Expat_printfToError4( parser, XML_Path );  e= E_XML_PARSER;  goto fin;\r
4443 }\r
4444 \r
4445 \r
4446 /*[Expat_printfToError4]*/\r
4447 static void  Expat_printfToError4( XML_Parser parser, const TCHAR* XML_Path )\r
4448 {\r
4449         Error4_printf( _T("<ERROR msg=\"%s\" file=\"%s(%lu)\"/>\n"),\r
4450                 XML_ErrorString( XML_GetErrorCode( parser ) ),\r
4451                 XML_Path,\r
4452                 XML_GetCurrentLineNumber(parser) );\r
4453 }\r
4454 \r
4455 \r
4456 /*[ParseXML2_onStartElement]*/\r
4457 static void  ParseXML2_onStartElement( void* UserData, const XML_Char* Name, const XML_Char** Atts )\r
4458 {\r
4459         ParseXML2_WorkClass*  work = (ParseXML2_WorkClass*) UserData;\r
4460         TCHAR*    xpath = (TCHAR*) DUMMY_INITIAL_VALUE;\r
4461         int*      xpath_lengths;\r
4462         int       old_depth = work->Status.Depth;\r
4463         int       new_depth = work->Status.Depth + 1;\r
4464 \r
4465         if ( work->e != 0 )  return;\r
4466 \r
4467 \r
4468         /* Call "work->OnText" */\r
4469         if ( work->OnText != DefaultFunction )\r
4470                 { ParseXML2_callOnText( work ); }\r
4471 \r
4472 \r
4473         /* Set "work->XPath" : Add "Name" */\r
4474         {\r
4475                 errnum_t  e;\r
4476                 int       old_xpath_length;\r
4477                 int       name_length = _tcslen( Name );\r
4478 \r
4479 \r
4480                 /* Set "old_xpath_length" */\r
4481                 xpath_lengths = (int*) work->XPathLengths.First;\r
4482                 if ( old_depth >= 0 )\r
4483                         { old_xpath_length = xpath_lengths[ old_depth ]; }\r
4484                 else\r
4485                         { old_xpath_length = 0; }  /* Length("/") == 1, But 0 for next operation */\r
4486 \r
4487                 /* Add "Name" to "work->XPath" */\r
4488                 e= Set2_expandIfOverByOffset( &work->XPath,\r
4489                         ( old_xpath_length + name_length + 2 ) * sizeof(TCHAR) );\r
4490                         IF(e)goto fin2;\r
4491                 xpath = (TCHAR*) work->XPath.First;\r
4492                 xpath[ old_xpath_length ] = _T('/');\r
4493                 memcpy( &xpath[ old_xpath_length + 1 ],  Name,  name_length * sizeof(TCHAR) );\r
4494                 xpath[ old_xpath_length + 1 + name_length ] = _T('\0');\r
4495 \r
4496                 /* "work->XPathLengths[]" = new XPath length */\r
4497                 e= Set2_expandIfOverByOffset( &work->XPathLengths, ( new_depth + 1 ) * sizeof(int) );\r
4498                         IF(e)goto fin2;\r
4499                 xpath_lengths = (int*) work->XPathLengths.First;\r
4500                 xpath_lengths[ new_depth ] = old_xpath_length + 1 + name_length;\r
4501 \r
4502                 e=0;\r
4503         fin2:\r
4504                 if (e) {\r
4505                         work->e = e;\r
4506                         return;\r
4507                 }\r
4508         }\r
4509 \r
4510 \r
4511         /* Call "work->OnStartElement" */\r
4512         work->Status.XPath = xpath;\r
4513         if ( old_depth >= 0 )\r
4514                 { work->Status.TagName = &xpath[ xpath_lengths[ old_depth ] + 1 ]; }\r
4515         else\r
4516                 { work->Status.TagName = &xpath[ 1 ]; }\r
4517         work->Status.u.OnStartElement.Attributes = Atts;\r
4518         work->Status.Depth += 1;\r
4519 \r
4520         work->e = work->OnStartElement( &work->Status );\r
4521 \r
4522         work->Status.u.OnStartElement.Attributes = NULL;\r
4523 \r
4524         work->Status.PreviousCallbackType = F_ParseXML2_OnStartElement;\r
4525 }\r
4526 \r
4527 \r
4528 /*[ParseXML2_onEndElement]*/\r
4529 static void  ParseXML2_onEndElement( void* UserData, const XML_Char* Name )\r
4530 {\r
4531         ParseXML2_WorkClass*  work = (ParseXML2_WorkClass*) UserData;\r
4532         TCHAR*  xpath = (TCHAR*) work->XPath.First;\r
4533         int*    xpath_lengths = (int*) work->XPathLengths.First;\r
4534         int     new_depth = work->Status.Depth - 1;\r
4535 \r
4536         UNREFERENCED_VARIABLE( Name );\r
4537 \r
4538         if ( work->e != 0 )  return;\r
4539 \r
4540         if ( new_depth >= 0 )\r
4541                 { work->Status.TagName = &xpath[ xpath_lengths[ new_depth ] + 1 ]; }\r
4542         else\r
4543                 { work->Status.TagName = &xpath[ 1 ]; }\r
4544 \r
4545 \r
4546         /* Call "work->OnText" */\r
4547         if ( work->OnText != DefaultFunction )\r
4548                 { ParseXML2_callOnText( work ); }\r
4549 \r
4550 \r
4551         /* Call "work->OnEndElement" */\r
4552         work->e = work->OnEndElement( &work->Status );\r
4553         work->Status.Depth -= 1;\r
4554 \r
4555 \r
4556         /* Set "work->XPath" : Remove "Name" */\r
4557         if ( new_depth >= 0 ) {\r
4558                 xpath[ xpath_lengths[ new_depth ] ] = _T('\0');\r
4559                 if ( new_depth - 1 >= 0 )\r
4560                         { work->Status.TagName = &xpath[ xpath_lengths[ new_depth - 1 ] + 1 ]; }\r
4561                 else\r
4562                         { work->Status.TagName = &xpath[ 1 ]; }\r
4563         }\r
4564         else {\r
4565                 xpath[ 1 ] = _T('\0');  /* xpath = "/" */\r
4566                 work->Status.TagName = &xpath[ 0 ];\r
4567         }\r
4568 \r
4569         work->Status.PreviousCallbackType = F_ParseXML2_OnEndElement;\r
4570 }\r
4571 \r
4572 \r
4573 /*[ParseXML2_onText]*/\r
4574 static void  ParseXML2_onText( void* UserData, const XML_Char* Text, int TextLength )\r
4575 {\r
4576         ParseXML2_WorkClass*  work = (ParseXML2_WorkClass*) UserData;\r
4577 \r
4578         if ( work->e != 0 )  return;\r
4579 \r
4580         if ( work->OnText != DefaultFunction ) {\r
4581 \r
4582                 #if 1\r
4583                         work->e = StrFile_writeBinary( &work->TextBuffer, Text, TextLength * sizeof(TCHAR) );\r
4584 \r
4585                         if ( work->TextStartLineNum == 0 )\r
4586                                 { work->TextStartLineNum = work->Status.LineNum; }\r
4587                 #else\r
4588                         work->Status.u.OnText.Text = Text;\r
4589                         work->Status.u.OnText.TextLength = TextLength;\r
4590 \r
4591                         work->e = work->OnText( &work->Status );\r
4592 \r
4593                         work->Status.u.OnText.Text = NULL;\r
4594                         work->Status.u.OnText.TextLength = 0;\r
4595 \r
4596                         work->Status.PreviousCallbackType = F_ParseXML2_OnText;\r
4597                 #endif\r
4598         }\r
4599 }\r
4600 \r
4601 \r
4602 /*[ParseXML2_callOnText]*/\r
4603 static void  ParseXML2_callOnText( ParseXML2_WorkClass* work )\r
4604 {\r
4605         if ( work->TextStartLineNum != 0 ) {\r
4606                 int  line_num_back_up = work->Status.LineNum;\r
4607 \r
4608                 work->Status.u.OnText.Text = work->TextBuffer.Buffer;\r
4609                 work->Status.u.OnText.TextLength = (TCHAR*) work->TextBuffer.Pointer -\r
4610                         (TCHAR*) work->TextBuffer.Buffer;\r
4611                 work->Status.LineNum = work->TextStartLineNum;\r
4612 \r
4613                 work->e = work->OnText( &work->Status );\r
4614 \r
4615                 if ( work->e == 0 ) {\r
4616                         work->e = StrFile_setPointer( &work->TextBuffer, 0 );\r
4617                                 IF( work->e ) __noop();\r
4618                 }\r
4619                 work->Status.LineNum = line_num_back_up;\r
4620                 work->TextStartLineNum = 0;\r
4621                 work->Status.PreviousCallbackType = F_ParseXML2_OnText;\r
4622         }\r
4623 }\r
4624 \r
4625 \r
4626  \r
4627 /***********************************************************************\r
4628   <<< [AppKey] >>> \r
4629 ************************************************************************/\r
4630 static errnum_t  AppKey_create( AppKey** out_m );\r
4631 static bool      AppKey_isSame( AppKey* m );\r
4632 static void      Writables_initConst( Writables* m );\r
4633 static errnum_t  Writables_init( Writables* m, AppKey* Key );\r
4634 static errnum_t  Writables_finish( Writables* m, int e );\r
4635 static bool      Writables_isInited( Writables* m );\r
4636 static errnum_t  Writables_clearPaths( Writables* m );\r
4637 static errnum_t  Writables_create( Writables** out_m, AppKey* Key );\r
4638 static errnum_t  Writables_copyToConst( Writables* To, Writables* From );\r
4639 \r
4640 \r
4641 typedef struct _CurrentWritables  CurrentWritables;\r
4642 struct _CurrentWritables {\r
4643         Writables  m_CurrentWritables;\r
4644         TCHAR*   m_ProgramFiles;  size_t  m_ProgramFiles_Len;\r
4645         TCHAR*   m_windir;        size_t  m_windir_Len;\r
4646         TCHAR*   m_APPDATA;       size_t  m_APPDATA_Len;\r
4647         TCHAR*   m_LOCALAPPDATA;  size_t  m_LOCALAPPDATA_Len;\r
4648 };\r
4649 static void      CurrentWritables_initConst( CurrentWritables* m );\r
4650 static errnum_t  CurrentWritables_init( CurrentWritables* m );\r
4651 static errnum_t  CurrentWritables_finish( CurrentWritables* m, int e );\r
4652 static errnum_t  CurrentWritables_askFileAccess( CurrentWritables* m, const TCHAR* FullPath );\r
4653 \r
4654 \r
4655 //////////////////////////////\r
4656 \r
4657 static  AppKey   g_AppKey;\r
4658 static  AppKey*  g_AppKeyPrivate;\r
4659 \r
4660 // under g_AppKey\r
4661 Writables  g_DefaultWritables;\r
4662 Writables  g_CurrentWritables; // public\r
4663 static CurrentWritables  g_CurrentWritablesPrivate;\r
4664 \r
4665 \r
4666 static errnum_t  AppKey_create( AppKey** out_m )\r
4667 {\r
4668         errnum_t  e;\r
4669 \r
4670         IF( g_AppKeyPrivate != NULL ) { e=1; goto fin; }\r
4671                 // AppKey_newWritable \82Ì in_out_m = NULL \82Ì\82Æ\82«\82Í\81A2\89ñ\8cÄ\82Ñ\8fo\82·\82±\82Æ\82Í\82Å\82«\82Ü\82¹\82ñ\81B\r
4672 \r
4673         Writables_initConst( &g_DefaultWritables );\r
4674         CurrentWritables_initConst( &g_CurrentWritablesPrivate );\r
4675 \r
4676         e= CurrentWritables_init( &g_CurrentWritablesPrivate ); IF(e)goto fin;\r
4677         e= Writables_copyToConst( &g_CurrentWritables, NULL ); IF(e)goto fin;\r
4678 \r
4679         *out_m = &g_AppKey;\r
4680         g_AppKeyPrivate = &g_AppKey;\r
4681 \r
4682         e=0;\r
4683 fin:\r
4684         return  e;\r
4685 }\r
4686 \r
4687 \r
4688 static bool  AppKey_isSame( AppKey* m )\r
4689 {\r
4690         return  ( m == g_AppKeyPrivate );\r
4691 }\r
4692 \r
4693 \r
4694 void  AppKey_initGlobal_const()\r
4695 {\r
4696         Writables_initConst( &g_DefaultWritables );\r
4697 }\r
4698 \r
4699 \r
4700 errnum_t  AppKey_finishGlobal( errnum_t e )\r
4701 {\r
4702         errnum_t  ee;\r
4703 \r
4704         e= Writables_finish( &g_DefaultWritables, e );\r
4705         e= CurrentWritables_finish( &g_CurrentWritablesPrivate, e );\r
4706         ee= Writables_copyToConst( &g_CurrentWritables, NULL ); IF(ee&&!e)e=ee;\r
4707 \r
4708         return  e;\r
4709 }\r
4710 \r
4711 \r
4712  \r
4713 /***********************************************************************\r
4714   <<< [AppKey_newWritable_Sub] >>> \r
4715 ************************************************************************/\r
4716 errnum_t  AppKey_newWritable_Sub( AppKey** in_out_m,  Writables** out_Writable,\r
4717         va_list  va,\r
4718         TCHAR**  in_Paths,  int  in_PathCount )\r
4719 {\r
4720         errnum_t    e;\r
4721         AppKey*     m = NULL;\r
4722         Writables*  wr = NULL;\r
4723 #if Uses_OutMallocIDTool\r
4724         bool  is_prev_out_malloc;\r
4725 \r
4726         is_prev_out_malloc = OutMallocID_setEnable( false );\r
4727 #endif\r
4728 \r
4729 \r
4730         //=== AppKey* m \82ð\97L\8cø\82É\82·\82é\r
4731         if ( in_out_m == NULL ) {  // \8d¡\89ñ\82Ì\8aÖ\90\94\82Ì\92\86\82¾\82¯\82Å\8eQ\8fÆ\82·\82é\r
4732                 e= AppKey_create( &m ); IF(e)goto resume;\r
4733         }\r
4734         else if ( *in_out_m == NULL ) {  // \82P\89ñ\96Ú\82É\96{\8aÖ\90\94\82ð\8cÄ\82Ñ\8fo\82µ\82½\83\82\83W\83\85\81[\83\8b\82É\93n\82·\r
4735                 e= AppKey_create( &m ); IF(e)goto resume;\r
4736                 *in_out_m = m;\r
4737         }\r
4738         else {  // \96{\8aÖ\90\94\82ð\8cÄ\82Ñ\8fo\82µ\82½\83\82\83W\83\85\81[\83\8b\82©\82ç\93n\82Á\82½\82à\82Ì\82ð\8eg\82¤\r
4739                 m = *in_out_m;\r
4740         }\r
4741 \r
4742 \r
4743         //=== \90³\8bK\82Ì AppKey \82©\83`\83F\83b\83N\82·\82é\r
4744         IF( ! AppKey_isSame( m ) )goto err;\r
4745 \r
4746 \r
4747         //=== Writable \82ð\90\90¬\82·\82é\r
4748         if ( out_Writable == NULL ) {\r
4749                 wr = &g_DefaultWritables;\r
4750                 e= Writables_finish( wr, 0 ); IF(e)goto resume;\r
4751                 e= Writables_init( wr, m ); IF(e)goto resume;\r
4752         }\r
4753         else {\r
4754                 e= Writables_create( &wr, m ); IF(e)goto resume;\r
4755                 *out_Writable = wr;\r
4756         }\r
4757 \r
4758 \r
4759         //=== Writable \82É\83p\83X\82ð\93o\98^\82·\82é\r
4760         if ( in_Paths == NULL ) {\r
4761                 TCHAR*   path;\r
4762                 int  i;\r
4763 \r
4764                 for ( i=0; ; i++ ) {\r
4765                         path = va_arg( va, TCHAR* );\r
4766                         if ( path == NULL )  break;\r
4767                         IF( i == 5 ) goto err;  // \8dÅ\8cã\82Ì NULL \96Y\82ê\91Î\8dô\r
4768 \r
4769                         e= Writables_add( wr, m, path ); IF(e)goto resume;\r
4770                 }\r
4771         }\r
4772         else {\r
4773                 int  i;\r
4774 \r
4775                 for ( i = 0;  i < in_PathCount;  i += 1 ) {\r
4776                         e= Writables_add( wr, m, in_Paths[i] ); IF(e){goto fin;}\r
4777                 }\r
4778         }\r
4779 \r
4780         #if defined(TempFile_get)\r
4781         {\r
4782                 TempFile*   temp;\r
4783 \r
4784                 e= TempFile_get( &temp ); IF(e)goto resume;\r
4785                 e= Writables_add( wr, m, temp->TempPath ); IF(e)goto resume;\r
4786         }\r
4787         #endif\r
4788 \r
4789 \r
4790         //=== \82·\82®\82É Writable \82ð\97L\8cø\82É\82·\82é\r
4791         if ( out_Writable == NULL ) {\r
4792                 e= Writables_enable( wr ); IF(e)goto resume;\r
4793         }\r
4794 \r
4795         e=0;\r
4796 fin:\r
4797         #if Uses_OutMallocIDTool\r
4798                 OutMallocID_setEnable( is_prev_out_malloc );\r
4799         #endif\r
4800         return  e;\r
4801 \r
4802 err:  e = E_OTHERS;  goto resume;\r
4803 resume:\r
4804         if ( wr != NULL ) {\r
4805                 if ( out_Writable == NULL )\r
4806                         e= Writables_finish( wr, e );  // g_DefaultWritables\r
4807                 else\r
4808                         e= Writables_delete( wr, e );\r
4809         }\r
4810         goto fin;\r
4811 }\r
4812 \r
4813 \r
4814  \r
4815 /***********************************************************************\r
4816   <<< [AppKey_newWritable] >>> \r
4817 ************************************************************************/\r
4818 errnum_t  AppKey_newWritable( AppKey** in_out_m,  Writables** out_Writable,  ... )\r
4819 {\r
4820         errnum_t  e;\r
4821         va_list  va;\r
4822 \r
4823         va_start( va, out_Writable );\r
4824         e = AppKey_newWritable_Sub( in_out_m,  out_Writable,  va,  NULL,  0 );\r
4825         va_end( va );\r
4826 \r
4827         return  e;\r
4828 }\r
4829 \r
4830 \r
4831  \r
4832 /***********************************************************************\r
4833   <<< [AppKey_newWritable_byArray] >>> \r
4834 ************************************************************************/\r
4835 errnum_t  AppKey_newWritable_byArray( AppKey** in_out_m,  Writables** out_Writable,\r
4836         TCHAR**  in_Paths,  int  in_PathCount )\r
4837 {\r
4838         IF ( in_Paths == NULL ) {\r
4839                 return  E_OTHERS;\r
4840         } else {\r
4841                 return  AppKey_newWritable_Sub( in_out_m,  out_Writable,  NULL,\r
4842                         in_Paths,  in_PathCount );\r
4843         }\r
4844 }\r
4845 \r
4846 \r
4847  \r
4848 /***********************************************************************\r
4849   <<< [AppKey_addNewWritableFolder] \83`\83F\83b\83N\82·\82é\81A\82Ü\82½\82Í\92Ç\89Á\82·\82é >>> \r
4850 ************************************************************************/\r
4851 errnum_t  AppKey_addNewWritableFolder_Sub( const TCHAR* Path, bool* out_IsWritable );\r
4852 \r
4853 errnum_t  AppKey_addNewWritableFolder( const TCHAR* Path )\r
4854 {\r
4855         errnum_t  e;\r
4856         bool  is_writable;\r
4857 \r
4858         e= AppKey_addNewWritableFolder_Sub( Path, &is_writable ); IF(e){goto fin;}\r
4859         IF ( ! is_writable ) { e=E_OUT_OF_WRITABLE; goto fin; }\r
4860                 // Path (abs_path) \82Í\81AAppKey_newWritable \82Å\8b\96\89Â\82³\82ê\82Ä\82¢\82Ü\82¹\82ñ\81B\r
4861                 // \83E\83H\83b\83`\81E\83E\83B\83\93\83h\83E\82É g_CurrentWritables.m_Paths,3 \82È\82Ç\82ð\93ü\97Í\82µ\82Ä\r
4862                 // \8b\96\89Â\82³\82ê\82Ä\82¢\82é\83p\83X\82ð\8am\94F\82µ\82Ä\82­\82¾\82³\82¢\81B\r
4863 \r
4864         e=0;\r
4865 fin:\r
4866         return  e;\r
4867 }\r
4868 \r
4869 errnum_t  AppKey_addNewWritableFolder_Sub( const TCHAR* Path, bool* out_IsWritable )\r
4870 {\r
4871         errnum_t    e;\r
4872         TCHAR**     pp;\r
4873         TCHAR**     pp_over;\r
4874         Writables*  wr = &g_CurrentWritablesPrivate.m_CurrentWritables;\r
4875         size_t      path_len;\r
4876         TCHAR       abs_path[MAX_PATH];\r
4877 \r
4878         *out_IsWritable = true;\r
4879 \r
4880         if ( g_AppKeyPrivate == NULL ) {\r
4881                 e= AppKey_newWritable( NULL, NULL, ".", NULL ); IF(e){goto fin;}\r
4882         }\r
4883 \r
4884         e= StrT_getFullPath( abs_path, sizeof(abs_path), Path, NULL ); IF(e){goto fin;}\r
4885 \r
4886         pp_over = wr->m_Paths + wr->m_nPath;\r
4887         for ( pp = wr->m_Paths;  ;  pp++ ) {\r
4888                 if ( pp >= pp_over ) {\r
4889                         *out_IsWritable = false;\r
4890                         break;\r
4891                 }\r
4892                 path_len = _tcslen( *pp );\r
4893                 if ( _tcsnicmp( *pp, abs_path, path_len ) == 0 &&\r
4894                         ( abs_path[ path_len ] == _T('\\') || abs_path[ path_len ] == _T('\0') ) )\r
4895                 {\r
4896                         break;\r
4897                 }\r
4898         }\r
4899 \r
4900         e=0;\r
4901 fin:\r
4902         return  e;\r
4903 }\r
4904 \r
4905 \r
4906  \r
4907 /***********************************************************************\r
4908   <<< [AppKey_addWritableFolder] \83`\83F\83b\83N\82µ\82È\82¢\82Å\81A\92Ç\89Á\82·\82é >>> \r
4909 ************************************************************************/\r
4910 errnum_t  AppKey_addWritableFolder( AppKey* m, const TCHAR* Path )\r
4911 {\r
4912         errnum_t    e;\r
4913         Writables*  wr = &g_CurrentWritablesPrivate.m_CurrentWritables;\r
4914         bool        is_writable;\r
4915 \r
4916         e= AppKey_addNewWritableFolder_Sub( Path, &is_writable ); IF(e){goto fin;}\r
4917         if ( ! is_writable ) {\r
4918                 e= Writables_add( wr, m, Path ); IF(e){goto fin;}\r
4919         }\r
4920 \r
4921         e=0;\r
4922 fin:\r
4923         return  e;\r
4924 }\r
4925 \r
4926 \r
4927  \r
4928 /***********************************************************************\r
4929   <<< [AppKey_checkWritable] >>> \r
4930 ************************************************************************/\r
4931 errnum_t  AppKey_checkWritable( const TCHAR* Path )\r
4932 {\r
4933         return  AppKey_addNewWritableFolder( Path );\r
4934 }\r
4935 \r
4936 \r
4937  \r
4938 /***********************************************************************\r
4939   <<< [Writables_init] >>> \r
4940 ************************************************************************/\r
4941 static void  Writables_initConst( Writables* m )\r
4942 {\r
4943         m->m_Paths = NULL;\r
4944         m->m_nPath = -1;\r
4945 }\r
4946 \r
4947 \r
4948 static errnum_t  Writables_init( Writables* m, AppKey* Key )\r
4949 {\r
4950         IF( ! AppKey_isSame( Key ) ) return E_OTHERS;\r
4951 \r
4952         m->m_Paths = NULL;\r
4953         m->m_nPath = 0;\r
4954         return  0;\r
4955 }\r
4956 \r
4957 \r
4958 static errnum_t  Writables_finish( Writables* m, int e )\r
4959 {\r
4960         errnum_t  ee;\r
4961 \r
4962         ee= Writables_clearPaths( m ); IF(ee&&!e) e=ee;\r
4963         m->m_nPath = -1;\r
4964         return  e;\r
4965 }\r
4966 \r
4967 \r
4968 static bool  Writables_isInited( Writables* m )\r
4969 {\r
4970         return  ( m->m_nPath != -1 );\r
4971 }\r
4972 \r
4973 \r
4974 static errnum_t  Writables_clearPaths( Writables* m )\r
4975 {\r
4976         TCHAR**  p;\r
4977         TCHAR**  p_over;\r
4978 \r
4979         if ( m->m_Paths != NULL ) {\r
4980                 p_over = m->m_Paths + m->m_nPath;\r
4981                 for ( p = m->m_Paths;  p < p_over;  p++ ) {\r
4982                         free( *p );\r
4983                 }\r
4984                 free( m->m_Paths );  m->m_Paths = NULL;\r
4985         }\r
4986         m->m_nPath = 0;\r
4987         return  0;\r
4988 }\r
4989 \r
4990 \r
4991 static errnum_t  Writables_create( Writables** out_m, AppKey* Key )\r
4992 {\r
4993         errnum_t    e;\r
4994         Writables*  m;\r
4995 \r
4996         m = (Writables*) malloc( sizeof(*m) ); IF(m==NULL)return E_FEW_MEMORY;\r
4997         Writables_initConst( m );\r
4998         e= Writables_init( m, Key ); IF(e)goto resume;\r
4999         *out_m = m;\r
5000         return  0;\r
5001 resume: Writables_delete( m, 0 ); free(m); return  e;\r
5002 }\r
5003 \r
5004 \r
5005 errnum_t  Writables_delete( Writables* m, errnum_t e )\r
5006 {\r
5007         if ( m == NULL ) goto fin;\r
5008         e= Writables_finish( m, e );\r
5009         free( m );\r
5010 fin:\r
5011         return  e;\r
5012 }\r
5013 \r
5014 \r
5015  \r
5016 /***********************************************************************\r
5017   <<< [Writables_add] >>> \r
5018 ************************************************************************/\r
5019 int  Writables_add( Writables* m, AppKey* Key, const TCHAR* Path )\r
5020 {\r
5021         int  e;\r
5022         TCHAR**   pp;\r
5023         TCHAR*    p  = NULL;\r
5024         size_t    path_size;\r
5025         TCHAR     abs_path[MAX_PATH];\r
5026 \r
5027         IF( ! AppKey_isSame( Key ) )goto err;\r
5028         if ( Path[0] == _T('\0') ) return 0;\r
5029 \r
5030         e= StrT_getFullPath( abs_path, sizeof(abs_path), Path, NULL ); IF(e)goto resume;\r
5031 \r
5032         e= CurrentWritables_askFileAccess( &g_CurrentWritablesPrivate, abs_path ); IF(e)goto resume;\r
5033 \r
5034         pp = (TCHAR**) realloc( m->m_Paths, (m->m_nPath + 1) * sizeof(TCHAR*) );\r
5035         IF( pp == NULL ) goto err;\r
5036         m->m_Paths = pp;\r
5037 \r
5038         path_size = (_tcslen( abs_path ) + 1) * sizeof(TCHAR);\r
5039         p = (TCHAR*) malloc( path_size );\r
5040         m->m_Paths[ m->m_nPath ] = p;\r
5041         IF( p == NULL )goto err;\r
5042 \r
5043         memcpy( p, abs_path, path_size );\r
5044         if ( p[ path_size/sizeof(TCHAR) - 2 ] == _T('\\') )\r
5045                          p[ path_size/sizeof(TCHAR) - 2 ] =  _T('\0');\r
5046         m->m_nPath ++;\r
5047 \r
5048         e=0;\r
5049 fin:\r
5050         return  e;\r
5051 \r
5052 err:  e = E_OTHERS;  goto resume;\r
5053 resume:\r
5054         if ( p != NULL )  free( p );\r
5055         goto fin;\r
5056 }\r
5057 \r
5058 \r
5059 int  Writables_remove( Writables* m, const TCHAR* Path )\r
5060 {\r
5061         TCHAR**  pp;\r
5062         TCHAR**  pp_over;\r
5063 \r
5064         pp_over = m->m_Paths + m->m_nPath;\r
5065         for ( pp = m->m_Paths;  ;  pp++ ) {\r
5066                 if ( pp >= pp_over )  return  0;\r
5067                 if ( _tcscmp( *pp, Path ) == 0 )  break;\r
5068         }\r
5069         free( *pp );\r
5070         memmove( pp, pp+1, (char*)pp - (char*)pp_over - sizeof(TCHAR) );\r
5071         m->m_nPath --;\r
5072 \r
5073         #if _DEBUG\r
5074                 *( pp_over - 1 ) = NULL;\r
5075         #endif\r
5076 \r
5077         return  0;\r
5078 }\r
5079 \r
5080 \r
5081  \r
5082 /***********************************************************************\r
5083   <<< [Writables_enable] >>> \r
5084 ************************************************************************/\r
5085 int  Writables_enable( Writables* m )\r
5086 {\r
5087         int  e;\r
5088 \r
5089         e= Writables_copyToConst( &g_CurrentWritablesPrivate.m_CurrentWritables, m ); IF(e)goto fin;\r
5090         e= Writables_copyToConst( &g_CurrentWritables, &g_CurrentWritablesPrivate.m_CurrentWritables ); IF(e)goto fin;\r
5091 \r
5092         e=0;\r
5093 fin:\r
5094         return  e;\r
5095 }\r
5096 \r
5097 \r
5098 int  Writables_disable( Writables* m, int e )\r
5099 {\r
5100         int  ee;\r
5101 \r
5102         UNREFERENCED_VARIABLE( m );\r
5103 \r
5104         ee= Writables_copyToConst( &g_CurrentWritablesPrivate.m_CurrentWritables, NULL ); IF(ee&&!e)goto fin;\r
5105         ee= Writables_copyToConst( &g_CurrentWritables, NULL ); IF(ee&&!e)goto fin;\r
5106 \r
5107         e=0;\r
5108 fin:\r
5109         return  e;\r
5110 }\r
5111 \r
5112 \r
5113 static int  Writables_copyToConst( Writables* To, Writables* From )\r
5114 {\r
5115         int  e;\r
5116         TCHAR**  pp;\r
5117         TCHAR**  pp_over;\r
5118         TCHAR*   p2;\r
5119         TCHAR**  pp2;\r
5120         size_t   path_size;\r
5121 \r
5122         if ( To->m_Paths != NULL ) {\r
5123                 free( To->m_Paths );\r
5124                 To->m_Paths = NULL;\r
5125                 To->m_nPath = 0;\r
5126         }\r
5127 \r
5128         if ( From != NULL && From->m_nPath > 0 ) {\r
5129 \r
5130                 path_size = 0;\r
5131                 pp_over = From->m_Paths + From->m_nPath;\r
5132                 for ( pp = From->m_Paths;  pp < pp_over;  pp++ ) {\r
5133                         path_size += _tcslen( *pp ) + 1;\r
5134                 }\r
5135 \r
5136                 path_size = From->m_nPath * sizeof(TCHAR*) + path_size * sizeof(TCHAR);\r
5137                 To->m_Paths = (TCHAR**) malloc( path_size );\r
5138                 IF( To->m_Paths == NULL ) goto err;\r
5139 \r
5140                 p2 = (TCHAR*)( (char*)To->m_Paths + From->m_nPath * sizeof(TCHAR*) );\r
5141                 pp2 = To->m_Paths;\r
5142                 for ( pp = From->m_Paths;  pp < pp_over;  pp++ ) {\r
5143                         *pp2 = p2;\r
5144                         path_size = (_tcslen( *pp ) + 1) * sizeof(TCHAR);\r
5145                         memcpy( p2, *pp, path_size );\r
5146                         p2 = (TCHAR*)( (char*)p2 + path_size );\r
5147                         pp2 ++;\r
5148                 }\r
5149                 To->m_nPath = From->m_nPath;\r
5150         }\r
5151 \r
5152         e=0;\r
5153 fin:\r
5154         return  e;\r
5155 \r
5156 err:  e = E_OTHERS;  goto fin;\r
5157 }\r
5158 \r
5159  \r
5160 /***********************************************************************\r
5161   <<< [CurrentWritables] >>> \r
5162 ************************************************************************/\r
5163 static void  CurrentWritables_initConst( CurrentWritables* m )\r
5164 {\r
5165         Writables_initConst( &m->m_CurrentWritables );\r
5166         m->m_ProgramFiles = NULL;\r
5167         m->m_windir = NULL;\r
5168         m->m_APPDATA = NULL;\r
5169         m->m_LOCALAPPDATA = NULL;\r
5170 }\r
5171 \r
5172 \r
5173 static int  CurrentWritables_init( CurrentWritables* m )\r
5174 {\r
5175         int    e;\r
5176  #if Uses_OutMallocIDTool\r
5177         bool  is_prev_out_malloc;\r
5178 \r
5179         is_prev_out_malloc = OutMallocID_setEnable( false );\r
5180  #endif\r
5181 \r
5182         e= Writables_copyToConst( &m->m_CurrentWritables, NULL ); IF(e)goto fin;\r
5183 \r
5184         e= env_malloc( &m->m_ProgramFiles, &m->m_ProgramFiles_Len, _T("ProgramFiles") ); IF(e)goto fin;\r
5185         e= env_malloc( &m->m_windir,       &m->m_windir_Len,       _T("windir") ); IF(e)goto fin;\r
5186         e= env_malloc( &m->m_APPDATA,      &m->m_APPDATA_Len,      _T("APPDATA") ); IF(e)goto fin;\r
5187         // e= env_malloc( &m->m_LOCALAPPDATA, &m->m_LOCALAPPDATA_Len, _T("LOCALAPPDATA") ); IF(e)goto fin;\r
5188 \r
5189         e=0;\r
5190 fin:\r
5191  #if Uses_OutMallocIDTool\r
5192         OutMallocID_setEnable( is_prev_out_malloc );\r
5193  #endif\r
5194         return  e;\r
5195 }\r
5196 \r
5197 \r
5198 static int  CurrentWritables_finish( CurrentWritables* m, int e )\r
5199 {\r
5200         int  ee;\r
5201 \r
5202         ee= Writables_copyToConst( &m->m_CurrentWritables, NULL ); IF(ee&&!e)e=ee;\r
5203 \r
5204         if ( m->m_ProgramFiles != NULL )  free( m->m_ProgramFiles );\r
5205         if ( m->m_windir != NULL )        free( m->m_windir );\r
5206         if ( m->m_APPDATA != NULL )       free( m->m_APPDATA );\r
5207         if ( m->m_LOCALAPPDATA != NULL )  free( m->m_LOCALAPPDATA );\r
5208 \r
5209         m->m_ProgramFiles = NULL;\r
5210         m->m_windir = NULL;\r
5211         m->m_APPDATA = NULL;\r
5212         m->m_LOCALAPPDATA = NULL;\r
5213 \r
5214         return  e;\r
5215 }\r
5216 \r
5217 \r
5218 static int  CurrentWritables_askFileAccess_sub(\r
5219         const TCHAR* SystemPath,  size_t SystemPath_Len,  const TCHAR* FullPath, size_t FullPath_Len );\r
5220 \r
5221 static int  CurrentWritables_askFileAccess( CurrentWritables* m, const TCHAR* FullPath )\r
5222 {\r
5223         int  e;\r
5224         size_t  abs_len;\r
5225 \r
5226         abs_len = _tcslen( FullPath );\r
5227         e= CurrentWritables_askFileAccess_sub( m->m_ProgramFiles, m->m_ProgramFiles_Len, FullPath, abs_len ); IF(e)goto fin;\r
5228         e= CurrentWritables_askFileAccess_sub( m->m_windir,       m->m_windir_Len,       FullPath, abs_len ); IF(e)goto fin;\r
5229         e= CurrentWritables_askFileAccess_sub( m->m_APPDATA,      m->m_APPDATA_Len,      FullPath, abs_len ); IF(e)goto fin;\r
5230         e= CurrentWritables_askFileAccess_sub( m->m_LOCALAPPDATA, m->m_LOCALAPPDATA_Len, FullPath, abs_len ); IF(e)goto fin;\r
5231 \r
5232         e=0;\r
5233 fin:\r
5234         return  e;\r
5235 }\r
5236 \r
5237 \r
5238 static int  CurrentWritables_askFileAccess_sub(\r
5239         const TCHAR* SystemPath,  size_t SystemPath_Len,  const TCHAR* FullPath, size_t FullPath_Len )\r
5240 {\r
5241         if ( SystemPath == NULL )  return  0;\r
5242 \r
5243         IF ( _tcsncmp( SystemPath, FullPath, SystemPath_Len ) == 0 )\r
5244                 return  E_OUT_OF_WRITABLE;  // \83V\83X\83e\83\80\83t\83H\83\8b\83_\82Ì\92\86\82ð\8f\91\82«\8d\9e\82Ý\8b\96\89Â\82µ\82æ\82¤\82Æ\82µ\82Ä\82¢\82é\r
5245 \r
5246         IF ( _tcsncmp( SystemPath, FullPath, FullPath_Len ) == 0 )\r
5247                 return  E_OUT_OF_WRITABLE;  // \83V\83X\83e\83\80\83t\83H\83\8b\83_\82ð\8aÜ\82ß\82Ä\8b\96\89Â\8f\91\82«\8d\9e\82Ý\8b\96\89Â\82µ\82æ\82¤\82Æ\82µ\82Ä\82¢\82é\r
5248 \r
5249         return  0;\r
5250 }\r
5251 \r
5252 \r
5253  \r
5254 /*=================================================================*/\r
5255 /* <<< [Error4/Error4.c] >>> */ \r
5256 /*=================================================================*/\r
5257  \r
5258 /***********************************************************************\r
5259   <<< [Get_Error4_Variables] >>> \r
5260 ************************************************************************/\r
5261 static Error4_VariablesClass  gs;\r
5262 #ifdef _DEBUG\r
5263         extern Error4_VariablesClass*  g_Error4_Variables = &gs;\r
5264 #endif\r
5265 \r
5266 Error4_VariablesClass*  Get_Error4_Variables()\r
5267 {\r
5268         return  &gs;\r
5269 }\r
5270 \r
5271 \r
5272  \r
5273 /***********************************************************************\r
5274   <<< (SetBreakErrorID) >>> \r
5275 ************************************************************************/\r
5276 \r
5277 /*[DebugBreakR]*/\r
5278 void  DebugBreakR()\r
5279 {\r
5280         printf( "\83u\83\8c\81[\83N\82µ\82Ü\82·\81B\82à\82µ\83f\83o\83b\83K\81[\82ª\90Ú\91±\82³\82ê\82Ä\82¢\82È\82¯\82ê\82Î\8b­\90§\8fI\97¹\82µ\82Ü\82·\81B\n" );\r
5281         DebugBreak();\r
5282                 // Visual Studio 2008 \82Å\82Í\81A\82±\82±\82Å [ \83f\83o\83b\83O > \83X\83e\83b\83\83A\83E\83g ] \82µ\82È\82¢\82Æ\r
5283                 // \8cÄ\82Ñ\8fo\82µ\97\9a\97ð\82â\83E\83H\83b\83`\82Ì\93à\97e\82ª\90³\82µ\82­\82È\82è\82Ü\82¹\82ñ\81B\r
5284 }\r
5285 \r
5286 \r
5287 #if ENABLE_ERROR_BREAK_IN_ERROR_CLASS\r
5288 \r
5289 \r
5290 #if ! IS_MULTI_THREAD_ERROR_CLASS\r
5291         dll_global_g_DebugBreakCount  ErrorClass  g_Error;  /* \8f\89\8aú\92l\82Í\82·\82×\82Ä\83[\83\8d */\r
5292 #else\r
5293         dll_global_g_DebugBreakCount  GlobalErrorClass  g_GlobalError;\r
5294 \r
5295         static errnum_t  ErrorClass_initializeIfNot_Sub( ErrorClass** out_Error );\r
5296         static errnum_t  ErrorClass_initializeIfNot_Sub2(void);\r
5297 #endif\r
5298 \r
5299 \r
5300 #define  IF_  if  /* Error check for in "IF" macro */\r
5301 \r
5302 \r
5303 /*[SetBreakErrorID]*/\r
5304 void  SetBreakErrorID( int ErrorID )\r
5305 {\r
5306 #if ! IS_MULTI_THREAD_ERROR_CLASS\r
5307 \r
5308         ErrorClass*  err = &g_Error;\r
5309         bool         is_print;\r
5310 \r
5311         is_print = ( err->BreakErrorID != ErrorID );\r
5312 \r
5313         err->BreakErrorID = ErrorID;\r
5314                 /* printf \82Ì\92\86\82Å\94­\90\82·\82é\83G\83\89\81[\82Å\8e~\82ß\82é\82½\82ß */\r
5315 \r
5316         if ( is_print )\r
5317                 { printf( ">SetBreakErrorID( %d );\n", ErrorID ); }\r
5318 \r
5319 #else\r
5320 \r
5321         GlobalErrorClass*  err_global = &g_GlobalError;\r
5322 \r
5323         if ( err_global->BreakGlobalErrorID != ErrorID )\r
5324                 { printf( ">SetBreakErrorID( %d );\n", ErrorID ); }\r
5325         err_global->BreakGlobalErrorID = ErrorID;\r
5326 \r
5327 #endif\r
5328 }\r
5329 \r
5330 \r
5331 \r
5332 bool  OnRaisingError_Sub( const char* FilePath, int LineNum )\r
5333  // \96{\8aÖ\90\94\82Í\81AIF \83}\83N\83\8d\82Ì\92\86\82©\82ç\8cÄ\82Î\82ê\82Ü\82·\r
5334  // \95Ô\82è\92l\82Í\81A\83u\83\8c\81[\83N\82·\82é\82©\82Ç\82¤\82©\r
5335 {\r
5336 #if ! IS_MULTI_THREAD_ERROR_CLASS\r
5337 \r
5338         ErrorClass*  err = &g_Error;\r
5339         bool  is_break;\r
5340 \r
5341         /* \83G\83\89\81[\8e\9e\82Ì\92\86\92f\8f\88\97\9d\81i\83W\83\83\83\93\83v\81j\82ð\82µ\82Ä\82¢\82é\82Æ\82«\81i\8d\82\91¬\83\8a\83^\81[\83\93\81j */\r
5342         if ( err->IsError ) {\r
5343                 return  false;\r
5344         }\r
5345 \r
5346         /* \83G\83\89\81[\82ª\94­\90\82µ\82½\92¼\8cã\82Ì\82Æ\82« */\r
5347         err->ErrorID += 1;\r
5348         err->IsError = true;\r
5349         err->FilePath = FilePath;\r
5350         err->LineNum  = LineNum;\r
5351 \r
5352         #if ERR2_ENABLE_ERROR_LOG\r
5353                 printf( "<ERROR_LOG msg=\"raised\" ErrorID=\"%d\" ErrorObject=\"0x%08X\"/>\n",\r
5354                         err->ErrorID, (int) err );\r
5355         #endif\r
5356 \r
5357         is_break = ( err->ErrorID == err->BreakErrorID );\r
5358 \r
5359         if ( is_break ) {\r
5360                 printf( "Break in (%d) %s\n", LineNum, FilePath );\r
5361         }\r
5362         return  ( err->ErrorID == err->BreakErrorID );\r
5363 \r
5364 #else  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5365 \r
5366         errnum_t           e;\r
5367         bool               is_break = false;\r
5368         ErrorClass*        err;\r
5369 \r
5370         e= ErrorClass_initializeIfNot_Sub( &err ); IF_(e){goto fin;}\r
5371 \r
5372 \r
5373         /* \83G\83\89\81[\8e\9e\82Ì\92\86\92f\8f\88\97\9d\81i\83W\83\83\83\93\83v\81j\82ð\82µ\82Ä\82¢\82é\82Æ\82«\81i\8d\82\91¬\83\8a\83^\81[\83\93\81j */\r
5374         if ( err->IsError ) {\r
5375                 return  false;\r
5376         }\r
5377 \r
5378         /* \83G\83\89\81[\82ª\94­\90\82µ\82½\92¼\8cã\82Ì\82Æ\82« */\r
5379         else {\r
5380                 GlobalErrorClass*  err_global = &g_GlobalError;\r
5381 \r
5382                 EnterCriticalSection( &err_global->CriticalSection );\r
5383 \r
5384 \r
5385                 err_global->ErrorThreadCount += 1;\r
5386                 err_global->RaisedGlobalErrorID += 1;\r
5387                 err->GlobalErrorID = err_global->RaisedGlobalErrorID;\r
5388 \r
5389                 err->ErrorID += 1;\r
5390                 err->IsError = true;\r
5391                 err->FilePath = FilePath;\r
5392                 err->LineNum  = LineNum;\r
5393 \r
5394                 is_break = ( err->ErrorID == err->BreakErrorID ) ||\r
5395                         ( err->GlobalErrorID == err_global->BreakGlobalErrorID );\r
5396 \r
5397 \r
5398                 /* \82±\82±\82æ\82è\88È\8d~\82Í\81AIF \83}\83N\83\8d\82È\82Ç\82ð\8cÄ\82Ñ\8fo\82µ\89Â\94\\81i\83\8a\83G\83\93\83g\83\89\83\93\83g\89Â\94\\81j */\r
5399                 /* \8fã\8bL\82Ì if ( err->IsError ) \82Å\81A\82·\82®\96ß\82é\82½\82ß */\r
5400 \r
5401 \r
5402                 #if ERR2_ENABLE_ERROR_LOG\r
5403                         printf( "<ERROR_LOG msg=\"raised\" ErrorID=\"%d\" ErrorObject=\"0x%08X\"/>\n",\r
5404                                 err->GlobalErrorID, (int) err );\r
5405                 #endif\r
5406 \r
5407 \r
5408                 if ( err->ErrorID == 1 ) {\r
5409                         FinalizerClass_initConst( &err->Finalizer, err, ErrorClass_finalize );\r
5410                         e= AddThreadLocalFinalizer( &err->Finalizer );\r
5411                 }\r
5412                 else {\r
5413                         e = 0;\r
5414                 }\r
5415                 LeaveCriticalSection( &err_global->CriticalSection );\r
5416                 IF(e){goto fin;}\r
5417         }\r
5418 \r
5419         e=0;\r
5420 fin:\r
5421         if ( is_break ) {\r
5422                 printf( "Break in (%d) %s\n", LineNum, FilePath );\r
5423         }\r
5424         return  is_break;\r
5425 \r
5426 #endif  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5427 }\r
5428 \r
5429 \r
5430 //[ClearError]\r
5431 void  ClearError()\r
5432 {\r
5433 #if ! IS_MULTI_THREAD_ERROR_CLASS\r
5434 \r
5435         ErrorClass*  err = &g_Error;\r
5436 \r
5437         #if ERR2_ENABLE_ERROR_LOG\r
5438         if ( err->IsError ) {\r
5439                 printf( "<ERROR_LOG msg=\"cleared\" ErrorID=\"%d\" ErrorObject=\"0x%08X\"/>\n",\r
5440                         err->ErrorID, (int) err );\r
5441         }\r
5442         #endif\r
5443 \r
5444         err->IsError = false;\r
5445 \r
5446 #else  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5447 \r
5448         errnum_t     e;\r
5449         ErrorClass*  err;\r
5450 \r
5451         e= ErrorClass_initializeIfNot_Sub( &err );\r
5452         if ( e == 0 ) {\r
5453                 #if ERR2_ENABLE_ERROR_LOG\r
5454                 if ( err->IsError )\r
5455                         printf( "<ERROR_LOG msg=\"cleared\" ErrorID=\"%d\" ErrorObject=\"0x%08X\"/>\n",\r
5456                                 err->GlobalErrorID, (int) err );\r
5457                 #endif\r
5458 \r
5459                 if ( err->IsError ) {\r
5460                         GlobalErrorClass*  err_global = &g_GlobalError;\r
5461 \r
5462                         EnterCriticalSection( &err_global->CriticalSection );\r
5463                         err_global->ErrorThreadCount -= 1;\r
5464                         LeaveCriticalSection( &err_global->CriticalSection );\r
5465 \r
5466                         err->IsError = false;\r
5467                 }\r
5468         }\r
5469         else {\r
5470                 #if ERR2_ENABLE_ERROR_LOG\r
5471                         printf( "<ERROR_LOG msg=\"clear_miss\"/>\n" );\r
5472                 #endif\r
5473         }\r
5474 \r
5475 #endif  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5476 }\r
5477 \r
5478 \r
5479 //[IfErrThenBreak]\r
5480 void  IfErrThenBreak()\r
5481 {\r
5482 #if ! IS_MULTI_THREAD_ERROR_CLASS\r
5483 \r
5484         ErrorClass*  err = &g_Error;\r
5485 \r
5486         if ( err->IsError  &&\r
5487                 ( err->ErrorID != err->BreakErrorID || err->BreakErrorID == 0 )\r
5488         ) {\r
5489                 printf( "in IfErrThenBreak\n" );\r
5490                 DebugBreakR();\r
5491 \r
5492                 // \83E\83H\83b\83`\82Å\81Aerr->ErrorID \82Ì\92l(N\82Æ\82·\82é)\82ð\8am\94F\82µ\82Ä\81A\r
5493                 // \83\81\83C\83\93\8aÖ\90\94\82Å SetBreakErrorID( N ); \82ð\8cÄ\82Ñ\8fo\82µ\82Ä\82­\82¾\82³\82¢\81B\r
5494                 // \83G\83\89\81[\82ª\94­\90\82µ\82½\8fê\8f\8a\82Í\81Aerr->FilePath, err->LineNum \82Å\82·\81B\r
5495                 // \90³\8fí\8fI\97¹\82µ\82Ä\82¢\82é\82Â\82à\82è\82È\82Ì\82É\82±\82±\82Å\83u\83\8c\81[\83N\82·\82é\82Æ\82«\82Í\81A\r
5496                 // ClearError() \82ð\96Y\82ê\82Ä\82¢\82é\89Â\94\\90«\82ª\82 \82è\82Ü\82·\81B\r
5497                 #if ERR2_ENABLE_ERROR_LOG\r
5498                         printf( "<ERROR_LOG msg=\"IfErrThenBreak\" ErrorID=\"%d\" BreakErrorID=\"%d\"/>\n",\r
5499                                 err->ErrorID, err->BreakErrorID );\r
5500                 #endif\r
5501 \r
5502                 {\r
5503                         char  str[512];\r
5504                         sprintf_s( str, _countof(str), "<ERROR file=\"%s(%d)\"/>\n",\r
5505                                 err->FilePath, err->LineNum );\r
5506                         OutputDebugStringA( str );\r
5507                 }\r
5508         }\r
5509         ClearError();\r
5510 \r
5511 #else  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5512 \r
5513         errnum_t           e;\r
5514         GlobalErrorClass*  err_global = &g_GlobalError;\r
5515         ErrorClass*        err;\r
5516 \r
5517         e= ErrorClass_initializeIfNot_Sub( &err );\r
5518         if ( e ) { DebugBreakR();  ClearError();  return; }  /* \93à\95\94\83G\83\89\81[ */\r
5519 \r
5520         if ( err_global->ErrorThreadCount != 0  &&\r
5521                 ( err->GlobalErrorID != err_global->BreakGlobalErrorID || err_global->BreakGlobalErrorID == 0 )\r
5522         ) {\r
5523                 printf( "in IfErrThenBreak\n" );\r
5524                 DebugBreakR();\r
5525 \r
5526                 // \83E\83H\83b\83`\82Å\81Aerr->GlobalErrorID \82Ì\92l(N\82Æ\82·\82é)\82ð\8am\94F\82µ\82Ä\81A\r
5527                 // \83\81\83C\83\93\8aÖ\90\94\82Å SetBreakErrorID( N ); \82ð\8cÄ\82Ñ\8fo\82µ\82Ä\82­\82¾\82³\82¢\81B\r
5528                 // \83G\83\89\81[\82ª\94­\90\82µ\82½\8fê\8f\8a\82Í\81Aerr->FilePath, err->LineNum \82Å\82·\81B\r
5529                 // \90³\8fí\8fI\97¹\82µ\82Ä\82¢\82é\82Â\82à\82è\82È\82Ì\82É\82±\82±\82Å\83u\83\8c\81[\83N\82·\82é\82Æ\82«\82Í\81A\r
5530                 // ClearError() \82ð\96Y\82ê\82Ä\82¢\82é\89Â\94\\90«\82ª\82 \82è\82Ü\82·\81B\r
5531                 #if ERR2_ENABLE_ERROR_LOG\r
5532                         printf( "<ERROR_LOG msg=\"IfErrThenBreak\" ErrorID=\"%d\" BreakErrorID=\"%d\"/>\n",\r
5533                                 err->ErrorID, err->BreakErrorID );\r
5534                 #endif\r
5535 \r
5536                 {\r
5537                         char  str[512];\r
5538                         sprintf_s( str, _countof(str), "<ERROR file=\"%s(%d)\"/>\n",\r
5539                                 err->FilePath, err->LineNum );\r
5540                         OutputDebugStringA( str );\r
5541                 }\r
5542         }\r
5543         ClearError();\r
5544 \r
5545 #endif  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5546 }\r
5547 \r
5548 \r
5549 //[PushErr]\r
5550 void  PushErr( ErrStackAreaClass* ErrStackArea )\r
5551 {\r
5552 #if ! IS_MULTI_THREAD_ERROR_CLASS\r
5553 \r
5554         ErrorClass*  err = &g_Error;\r
5555 \r
5556         ErrStackArea->ErrorID = err->ErrorID;\r
5557         ErrStackArea->IsError = err->IsError;\r
5558         err->IsError = false;\r
5559 \r
5560 #else  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5561 \r
5562         errnum_t     e;\r
5563         ErrorClass*  err;\r
5564 \r
5565         e= ErrorClass_initializeIfNot_Sub( &err );\r
5566         if ( e == 0 ) {\r
5567                 ErrStackArea->ErrorID = err->ErrorID;\r
5568                 ErrStackArea->IsError = err->IsError;\r
5569                 err->IsError = false;\r
5570         }\r
5571 \r
5572 #endif  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5573 }\r
5574 \r
5575 //[PopErr]\r
5576 void  PopErr(  ErrStackAreaClass* ErrStackArea )\r
5577 {\r
5578 #if ! IS_MULTI_THREAD_ERROR_CLASS\r
5579 \r
5580         ErrorClass*  err = &g_Error;\r
5581 \r
5582         if ( ErrStackArea->IsError )\r
5583                 { err->IsError = true; }\r
5584 \r
5585 #else  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5586 \r
5587         errnum_t     e;\r
5588         ErrorClass*  err;\r
5589 \r
5590         e= ErrorClass_initializeIfNot_Sub( &err );\r
5591         if ( e == 0 ) {\r
5592                 if ( ErrStackArea->IsError )\r
5593                         { err->IsError = true; }\r
5594         }\r
5595 \r
5596 #endif  /* IS_MULTI_THREAD_ERROR_CLASS */\r
5597 }\r
5598 \r
5599 \r
5600  \r
5601 /*[SetBreakErrorID:2]*/\r
5602 #undef  IF_\r
5603 \r
5604 \r
5605 #endif // ENABLE_ERROR_BREAK_IN_ERROR_CLASS\r
5606 \r
5607 \r
5608 //[MergeError]\r
5609 errnum_t  MergeError( errnum_t e, errnum_t ee )\r
5610 {\r
5611         if ( e == 0 ) { return  ee; }\r
5612         else          { /* ErrorLog_add( ee ); */ return  e; }\r
5613 }\r
5614 \r
5615 \r
5616  \r
5617 /***********************************************************************\r
5618   <<< [g_Error4_String] >>> \r
5619 ************************************************************************/\r
5620 TCHAR  g_Error4_String[4096];\r
5621 \r
5622 \r
5623  \r
5624 /***********************************************************************\r
5625   <<< [Error4_printf] >>> \r
5626 ************************************************************************/\r
5627 void  Error4_printf( const TCHAR* format, ... )\r
5628 {\r
5629         va_list  va;\r
5630         va_start( va, format );\r
5631         vstprintf_r( g_Error4_String, sizeof(g_Error4_String), format, va );\r
5632         va_end( va );\r
5633 }\r
5634 \r
5635 \r
5636  \r
5637 /***********************************************************************\r
5638   <<< [Error4_getErrStr] >>> \r
5639 ************************************************************************/\r
5640 void  Error4_getErrStr( int ErrNum, TCHAR* out_ErrStr, size_t ErrStrSize )\r
5641 {\r
5642         switch ( ErrNum ) {\r
5643 \r
5644                 case  0:\r
5645                         stprintf_r( out_ErrStr, ErrStrSize, _T("no error") );\r
5646                         break;\r
5647 \r
5648                 case  E_FEW_ARRAY:\r
5649                         stprintf_r( out_ErrStr, ErrStrSize,\r
5650                                 _T("<ERROR msg=\"\83v\83\8d\83O\83\89\83\80\93à\95\94\82Ì\94z\97ñ\83\81\83\82\83\8a\81[\82ª\95s\91«\82µ\82Ü\82µ\82½\81B\"/>") );\r
5651                         break;\r
5652 \r
5653                 case  E_FEW_MEMORY:\r
5654                         stprintf_r( out_ErrStr, ErrStrSize,\r
5655                                 _T("<ERROR msg=\"\83q\81[\83v\81E\83\81\83\82\83\8a\81[\82ª\95s\91«\82µ\82Ü\82µ\82½\81B\"/>") );\r
5656                         break;\r
5657 \r
5658                 #ifndef  __linux__\r
5659                 case  E_GET_LAST_ERROR: {\r
5660                         DWORD   err_win;\r
5661                         TCHAR*  str_pointer;\r
5662 \r
5663                         err_win = gs.WindowsLastError;\r
5664                         if ( err_win == 0 ) { err_win = GetLastError(); }\r
5665 \r
5666                         stprintf_part_r( out_ErrStr, ErrStrSize, out_ErrStr, &str_pointer,\r
5667                                 _T("<ERROR GetLastError=\"0x%08X\" GetLastErrorStr=\""), err_win );\r
5668                         FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,\r
5669                                 NULL, err_win, LANG_USER_DEFAULT,\r
5670                                 str_pointer,  (TCHAR*)( (char*)out_ErrStr + ErrStrSize ) - str_pointer, NULL );\r
5671                         str_pointer = StrT_chr( str_pointer, _T('\0') );\r
5672                         if ( *( str_pointer - 2 ) == _T('\r') && *( str_pointer - 1 ) == _T('\n') )\r
5673                                 str_pointer -= 2;\r
5674                         stcpy_part_r( out_ErrStr, ErrStrSize, str_pointer, NULL, _T("\"/>"), NULL );\r
5675                         break;\r
5676                 }\r
5677                 #endif\r
5678 \r
5679                 default:\r
5680                         if ( g_Error4_String[0] != '\0' )\r
5681                                 stprintf_r( out_ErrStr, ErrStrSize, _T("%s"), g_Error4_String );\r
5682                         else\r
5683                                 stprintf_r( out_ErrStr, ErrStrSize, _T("<ERROR errnum=\"%d\"/>"), ErrNum );\r
5684                         break;\r
5685         }\r
5686 }\r
5687 \r
5688 \r
5689  \r
5690 /***********************************************************************\r
5691   <<< [SaveWindowsLastError] >>> \r
5692 ************************************************************************/\r
5693 errnum_t  SaveWindowsLastError()\r
5694 {\r
5695         gs.WindowsLastError = GetLastError();\r
5696         return  E_GET_LAST_ERROR;\r
5697 }\r
5698 \r
5699 \r
5700  \r
5701 /***********************************************************************\r
5702   <<< [Error4_showToStdErr] >>> \r
5703 ************************************************************************/\r
5704 void  Error4_showToStdErr( int err_num )\r
5705 {\r
5706         Error4_showToStdIO( stderr, err_num );\r
5707 }\r
5708 \r
5709 \r
5710  \r
5711 /***********************************************************************\r
5712   <<< [Error4_showToStdIO] >>> \r
5713 ************************************************************************/\r
5714 void  Error4_showToStdIO( FILE* out, int err_num )\r
5715 {\r
5716         TCHAR  msg[1024];\r
5717         #if _UNICODE\r
5718                 char  msg2[1024];\r
5719         #endif\r
5720 \r
5721         if ( err_num != 0 ) {\r
5722                 Error4_getErrStr( err_num, msg, sizeof(msg) );\r
5723                 #if _UNICODE\r
5724                         setlocale( LC_ALL, ".OCP" );\r
5725                         sprintf_s( msg2, sizeof(msg2), "%S", msg );\r
5726                         fprintf( out, "%s\n", msg2 );  // _ftprintf_s \82Å\82Í\93ú\96{\8cê\82ª\8fo\82Ü\82¹\82ñ\r
5727                 #else\r
5728                         fprintf( out, "%s\n", msg );\r
5729                 #endif\r
5730 \r
5731                 #if ERR2_ENABLE_ERROR_BREAK\r
5732                         fprintf( out, "\81i\8aJ\94­\8eÒ\82Ö\81j\83\81\83C\83\93\8aÖ\90\94\82Å SetBreakErrorID( %d ); \82ð\8cÄ\82Ñ\8fo\82µ\82Ä\82­\82¾\82³\82¢\81B\n",\r
5733                                 g_Err2.ErrID );\r
5734                 #else\r
5735 #if 0\r
5736                         if ( err_num == E_FEW_MEMORY  ||  gs.WindowsLastError == ERROR_NOT_ENOUGH_MEMORY ) {\r
5737                                 /* Not show the message for developper */\r
5738                         }\r
5739                         else {\r
5740                                 fprintf( out, "\81i\8aJ\94­\8eÒ\82Ö\81jERR2_ENABLE_ERROR_BREAK \82ð\92è\8b`\82µ\82Ä\8dÄ\83R\83\93\83p\83C\83\8b\82µ\82Ä\82­\82¾\82³\82¢\81B\n" );\r
5741                         }\r
5742 #endif\r
5743                 #endif\r
5744         }\r
5745         IfErrThenBreak();\r
5746 }\r
5747 \r
5748 \r
5749  \r
5750 /***********************************************************************\r
5751   <<< [Error4_showToPrintf] >>> \r
5752 ************************************************************************/\r
5753 void  Error4_showToPrintf( int err_num )\r
5754 {\r
5755         TCHAR  msg[1024];\r
5756         #if _UNICODE\r
5757                 char  msg2[1024];\r
5758         #endif\r
5759 \r
5760         if ( err_num != 0 ) {\r
5761                 Error4_getErrStr( err_num, msg, sizeof(msg) );\r
5762                 #if _UNICODE\r
5763                         setlocale( LC_ALL, ".OCP" );\r
5764                         sprintf_s( msg2, sizeof(msg2), "%S", msg );\r
5765                         printf( "%s\n", msg2 );  // _ftprintf_s \82Å\82Í\93ú\96{\8cê\82ª\8fo\82Ü\82¹\82ñ\r
5766                 #else\r
5767                         printf( "%s\n", msg );\r
5768                 #endif\r
5769 \r
5770                 #if ERR2_ENABLE_ERROR_BREAK\r
5771                         fprintf( out, "\81i\8aJ\94­\8eÒ\82Ö\81j\83\81\83C\83\93\8aÖ\90\94\82Å SetBreakErrorID( %d ); \82ð\8cÄ\82Ñ\8fo\82µ\82Ä\82­\82¾\82³\82¢\81B\n",\r
5772                                 g_Err2.ErrID );\r
5773                 #else\r
5774 #if 0\r
5775                         if ( err_num == E_FEW_MEMORY  ||  gs.WindowsLastError == ERROR_NOT_ENOUGH_MEMORY ) {\r
5776                                 /* Not show the message for developper */\r
5777                         }\r
5778                         else {\r
5779                                 fprintf( out, "\81i\8aJ\94­\8eÒ\82Ö\81jERR2_ENABLE_ERROR_BREAK \82ð\92è\8b`\82µ\82Ä\8dÄ\83R\83\93\83p\83C\83\8b\82µ\82Ä\82­\82¾\82³\82¢\81B\n" );\r
5780                         }\r
5781 #endif\r
5782                 #endif\r
5783         }\r
5784         IfErrThenBreak();\r
5785 }\r
5786 \r
5787 \r
5788  \r
5789 /*=================================================================*/\r
5790 /* <<< [CRT_plus_2/CRT_plus_2.c] >>> */ \r
5791 /*=================================================================*/\r
5792  \r
5793 /**************************************************************************\r
5794  <<< [Interface] >>> \r
5795 ***************************************************************************/\r
5796 \r
5797 /*[DefaultFunction]*/\r
5798 errnum_t  DefaultFunction( void* self )\r
5799 {\r
5800         UNREFERENCED_VARIABLE( self );\r
5801         return  0;\r
5802 }\r
5803 \r
5804 /*[DefaultFunction_NotImplementYet]*/\r
5805 errnum_t  DefaultFunction_NotImplementYet( void* self )\r
5806 {\r
5807         UNREFERENCED_VARIABLE( self );\r
5808         return  E_NOT_IMPLEMENT_YET;\r
5809 }\r
5810 \r
5811 /*[DefaultFunction_Finalize]*/\r
5812 errnum_t  DefaultFunction_Finalize( void* self, errnum_t e )\r
5813 {\r
5814         UNREFERENCED_VARIABLE( self );\r
5815         return  e;\r
5816 }\r
5817 \r
5818 /*[VTableDefine_overwrite]*/\r
5819 errnum_t  VTableDefine_overwrite( VTableDefine* aVTable, size_t aVTable_ByteSize, int iMethod, void* Func )\r
5820 {\r
5821         VTableDefine*  p = aVTable;\r
5822         VTableDefine*  p_over = (VTableDefine*)( (char*)aVTable + aVTable_ByteSize );\r
5823 \r
5824         for ( ; p < p_over; p++ ) {\r
5825                 if ( p->m_IMethod == iMethod ) {\r
5826                         p->m_method = Func;\r
5827                         return  0;\r
5828                 }\r
5829         }\r
5830         return  E_NOT_FOUND_SYMBOL;\r
5831 }\r
5832 \r
5833 \r
5834  \r
5835 /*=================================================================*/\r
5836 /* <<< [StrT/StrT.c] >>> */ \r
5837 /*=================================================================*/\r
5838  \r
5839 /***********************************************************************\r
5840   <<< [StrT_cpy] >>> \r
5841 - _tcscpy is raising exception, if E_FEW_ARRAY\r
5842 ************************************************************************/\r
5843 errnum_t  StrT_cpy( TCHAR* Dst, size_t DstSize, const TCHAR* Src )\r
5844 {\r
5845         size_t  size;\r
5846 \r
5847         size = ( _tcslen( Src ) + 1 ) * sizeof(TCHAR);\r
5848         if ( size <= DstSize ) {\r
5849                 memcpy( Dst, Src, size );\r
5850                 return  0;\r
5851         }\r
5852         else {\r
5853                 memcpy( Dst, Src, DstSize - sizeof(TCHAR) );\r
5854                 *(TCHAR*)( (char*) Dst + DstSize ) = _T('\0');\r
5855                 return  E_FEW_ARRAY;\r
5856         }\r
5857 }\r
5858 \r
5859  \r
5860 /***********************************************************************\r
5861   <<< [StrT_chr] >>> \r
5862 ************************************************************************/\r
5863 TCHAR*  StrT_chr( const TCHAR* String, TCHAR Key )\r
5864 {\r
5865         const TCHAR*  return_value = _tcschr( String, Key );\r
5866 \r
5867         if ( return_value == NULL  &&  Key == _T('\0') ) {\r
5868                 return_value = String + _tcslen( String );\r
5869         }\r
5870 \r
5871         return  (TCHAR*) return_value;\r
5872 }\r
5873 \r
5874  \r
5875 /***********************************************************************\r
5876   <<< [StrT_chrNext] >>> \r
5877 ************************************************************************/\r
5878 TCHAR*  StrT_chrNext( const TCHAR* in_Start, TCHAR in_KeyCharactor )\r
5879 {\r
5880         const TCHAR*  p = _tcschr( in_Start, in_KeyCharactor );\r
5881 \r
5882         if ( p != NULL )\r
5883                 { p += 1; }\r
5884 \r
5885         return  (TCHAR*) p;\r
5886 }\r
5887 \r
5888  \r
5889 /***********************************************************************\r
5890   <<< [CharPointerArray_free] >>> \r
5891 ************************************************************************/\r
5892 errnum_t  CharPointerArray_free( TCHAR*** in_out_Strings,  int  in_StringCount,\r
5893         bool  in_IsFreePointers,  errnum_t  e )\r
5894 {\r
5895         TCHAR**  strings = *in_out_Strings;\r
5896         int      i;\r
5897 \r
5898         for ( i = 0;  i < in_StringCount;  i += 1 ) {\r
5899                 e= HeapMemory_free( &strings[i], e );\r
5900         }\r
5901 \r
5902         if ( in_IsFreePointers ) {\r
5903                 e= HeapMemory_free( in_out_Strings, e );\r
5904         }\r
5905 \r
5906         return  e;\r
5907 }\r
5908 \r
5909 \r
5910  \r
5911 /***********************************************************************\r
5912   <<< [MallocAndCopyString] >>> \r
5913 ************************************************************************/\r
5914 errnum_t  MallocAndCopyString( const TCHAR** out_NewString, const TCHAR* SourceString )\r
5915 {\r
5916         TCHAR*  str;\r
5917         size_t  size = ( _tcslen( SourceString ) + 1 ) * sizeof(TCHAR);\r
5918 \r
5919         ASSERT_D( *out_NewString == NULL, __noop() );\r
5920 \r
5921         str = (TCHAR*) malloc( size );\r
5922         if ( str == NULL ) { return  E_FEW_MEMORY; }\r
5923 \r
5924         memcpy( str, SourceString, size );\r
5925 \r
5926         *out_NewString = str;\r
5927         return  0;\r
5928 }\r
5929 \r
5930 \r
5931  \r
5932 /***********************************************************************\r
5933   <<< [MallocAndCopyString_char] >>> \r
5934 ************************************************************************/\r
5935 #ifdef _UNICODE\r
5936 errnum_t  MallocAndCopyString_char( const TCHAR** out_NewString, const char* SourceString )\r
5937 {\r
5938         TCHAR*  str;\r
5939         size_t  size = ( strlen( SourceString ) + 1 ) * sizeof(TCHAR);\r
5940         int     r;\r
5941 \r
5942         str = (TCHAR*) malloc( size );\r
5943         if ( str == NULL ) { return  E_FEW_MEMORY; }\r
5944 \r
5945         r = MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED, SourceString, -1, str, size / sizeof(TCHAR) );\r
5946         IF ( r == 0 ) {\r
5947                 free( str );\r
5948                 return  E_GET_LAST_ERROR;\r
5949         }\r
5950         *out_NewString = str;\r
5951         return  0;\r
5952 }\r
5953 #endif\r
5954 \r
5955 \r
5956  \r
5957 /***********************************************************************\r
5958   <<< [MallocAndCopyStringByLength] >>> \r
5959 ************************************************************************/\r
5960 errnum_t  MallocAndCopyStringByLength( const TCHAR** out_NewString, const TCHAR* SourceString,\r
5961         unsigned CountOfCharacter )\r
5962 {\r
5963         TCHAR*  str;\r
5964         size_t  size = ( CountOfCharacter + 1 ) * sizeof(TCHAR);\r
5965 \r
5966         ASSERT_D( *out_NewString == NULL, __noop() );\r
5967         ASSERT_D( CountOfCharacter < 0x7FFFFFFF, __noop() );\r
5968 \r
5969         str = (TCHAR*) malloc( size );\r
5970         if ( str == NULL ) { return  E_FEW_MEMORY; }\r
5971 \r
5972         memcpy( str, SourceString, size - sizeof(TCHAR) );\r
5973         str[ CountOfCharacter ] = _T('\0');\r
5974 \r
5975         *out_NewString = str;\r
5976         return  0;\r
5977 }\r
5978 \r
5979 \r
5980  \r
5981 /***********************************************************************\r
5982   <<< [StrT_chrs] >>> \r
5983 ************************************************************************/\r
5984 TCHAR*  StrT_chrs( const TCHAR* s, const TCHAR* keys )\r
5985 {\r
5986         if ( *keys == _T('\0') )  return  NULL;\r
5987 \r
5988         for ( ; *s != _T('\0'); s++ ) {\r
5989                 if ( _tcschr( keys, *s ) != NULL )\r
5990                         return  (TCHAR*) s;\r
5991         }\r
5992         return  NULL;\r
5993 }\r
5994 \r
5995 \r
5996  \r
5997 /***********************************************************************\r
5998   <<< [StrT_rstr] >>> \r
5999 ************************************************************************/\r
6000 TCHAR*  StrT_rstr( const TCHAR* String, const TCHAR* SearchStart, const TCHAR* Keyword,\r
6001         void* NullConfig )\r
6002 {\r
6003         const TCHAR*  p;\r
6004         int           keyword_length = _tcslen( Keyword );\r
6005         TCHAR         keyword_first = Keyword[0];\r
6006 \r
6007         UNREFERENCED_VARIABLE( NullConfig );\r
6008 \r
6009         p = SearchStart;\r
6010         while ( p >= String ) {\r
6011                 if ( *p == keyword_first ) {\r
6012                         if ( _tcsncmp( p, Keyword, keyword_length ) == 0 ) {\r
6013                                 return  (TCHAR*) p;\r
6014                         }\r
6015                 }\r
6016                 p -= 1;\r
6017         }\r
6018 \r
6019         return  NULL;\r
6020 }\r
6021 \r
6022 \r
6023  \r
6024 /***********************************************************************\r
6025   <<< [StrT_skip] >>> \r
6026 ************************************************************************/\r
6027 TCHAR*  StrT_skip( const TCHAR* String, const TCHAR* Keys )\r
6028 {\r
6029         if ( *Keys == _T('\0') ) { return  (TCHAR*) String; }\r
6030 \r
6031         for ( ; *String != _T('\0'); String += 1 ) {\r
6032                 if ( _tcschr( Keys, *String ) == NULL )\r
6033                         break;\r
6034         }\r
6035         return  (TCHAR*) String;\r
6036 }\r
6037 \r
6038 \r
6039  \r
6040 /***********************************************************************\r
6041   <<< [StrT_rskip] >>> \r
6042 ************************************************************************/\r
6043 TCHAR*  StrT_rskip( const TCHAR* String, const TCHAR* SearchStart, const TCHAR* Keys,\r
6044         void* NullConfig )\r
6045 {\r
6046         const TCHAR*  pointer;\r
6047 \r
6048         UNREFERENCED_VARIABLE( NullConfig );\r
6049 \r
6050         if ( *Keys == _T('\0') ) { return  (TCHAR*) SearchStart; }\r
6051 \r
6052         for ( pointer = SearchStart;  pointer >= String;  pointer -= 1 ) {\r
6053                 if ( _tcschr( Keys, *pointer ) == NULL )\r
6054                         { return  (TCHAR*) pointer; }\r
6055         }\r
6056         return  NULL;\r
6057 }\r
6058 \r
6059 \r
6060  \r
6061 /***********************************************************************\r
6062   <<< [StrT_isCIdentifier] >>> \r
6063 ************************************************************************/\r
6064 bool  StrT_isCIdentifier( TCHAR Character )\r
6065 {\r
6066         const TCHAR  c = Character;\r
6067 \r
6068         return  (\r
6069                 ( c >= _T('A')  &&  c <= _T('Z') ) ||\r
6070                 ( c >= _T('a')  &&  c <= _T('z') ) ||\r
6071                 ( c >= _T('0')  &&  c <= _T('9') ) ||\r
6072                 c == _T('_') );\r
6073 }\r
6074 \r
6075 \r
6076  \r
6077 /***********************************************************************\r
6078   <<< [StrT_searchOverOfCIdentifier] >>> \r
6079 ************************************************************************/\r
6080 TCHAR*  StrT_searchOverOfCIdentifier( const TCHAR* Text )\r
6081 {\r
6082         const TCHAR*  p;\r
6083 \r
6084         for ( p = Text;\r
6085                 StrT_isCIdentifier( *p );\r
6086                 p += 1 )\r
6087         {\r
6088         }\r
6089         return  (TCHAR*) p;\r
6090 }\r
6091 \r
6092 \r
6093  \r
6094 /***********************************************************************\r
6095   <<< [StrT_searchOverOfIdiom] >>> \r
6096 ************************************************************************/\r
6097 TCHAR*  StrT_searchOverOfIdiom( const TCHAR* Text )\r
6098 {\r
6099         const TCHAR*  p;\r
6100 \r
6101         p = Text;\r
6102         for ( p = Text;\r
6103                 StrT_isCIdentifier( *p )  ||  *p == _T(' ');\r
6104                 p += 1 )\r
6105         {\r
6106         }\r
6107 \r
6108         for ( p -= 1;\r
6109                 *p == _T(' ')  &&  p >= Text;\r
6110                 p -= 1 )\r
6111         {\r
6112         }\r
6113 \r
6114         return  (TCHAR*) p + 1;\r
6115 }\r
6116 \r
6117 \r
6118  \r
6119 /***********************************************************************\r
6120   <<< [StrT_convPartStrToPointer] >>> \r
6121 ************************************************************************/\r
6122 void*  StrT_convPartStrToPointer( const TCHAR* StringStart, const TCHAR* StringOver,\r
6123         const NameOnlyClass* Table, size_t TableSize, void* Default )\r
6124 {\r
6125         const NameOnlyClass*  p = Table;\r
6126         const NameOnlyClass*  p_over = (const NameOnlyClass*)( (uint8_t*) Table + TableSize );\r
6127 \r
6128         while ( p < p_over ) {\r
6129                 if ( StrT_cmp_part( StringStart, StringOver, p->Name ) == 0 ) {\r
6130                         return  (void*) p->Delegate;\r
6131                 }\r
6132                 p += 1;\r
6133         }\r
6134         return  Default;\r
6135 }\r
6136 \r
6137 \r
6138  \r
6139 /***********************************************************************\r
6140   <<< [StrT_convertNumToStr] >>> \r
6141 ************************************************************************/\r
6142 TCHAR*  StrT_convertNumToStr( int Number, const NameAndNumClass* Table, int TableCount,\r
6143         const TCHAR* DefaultStr )\r
6144 {\r
6145         const NameAndNumClass*  p;\r
6146         const NameAndNumClass*  p_over = Table + TableCount;\r
6147 \r
6148         for ( p = Table;  p < p_over;  p += 1 ) {\r
6149                 if ( p->Number == Number ) {\r
6150                         return  p->Name;\r
6151                 }\r
6152         }\r
6153         return  (TCHAR*) DefaultStr;\r
6154 }\r
6155 \r
6156 \r
6157  \r
6158 /***********************************************************************\r
6159   <<< [StrT_cmp_part] >>> \r
6160 ************************************************************************/\r
6161 int  StrT_cmp_part( const TCHAR* in_StringA_Start, const TCHAR* in_StringA_Over,\r
6162         const TCHAR* in_StringB )\r
6163 {\r
6164         const TCHAR*  a;\r
6165         const TCHAR*  b;\r
6166         TCHAR  aa;\r
6167         TCHAR  bb;\r
6168 \r
6169         a = in_StringA_Start;\r
6170         b = in_StringB;\r
6171 \r
6172         for (;;) {\r
6173                 if ( a >= in_StringA_Over ) {\r
6174                         bb = *b;\r
6175                         if ( bb == _T('\0') )\r
6176                                 { return  0; }\r
6177                         else\r
6178                                 { return  -bb; }\r
6179                 }\r
6180 \r
6181                 aa = *a;\r
6182                 bb = *b;\r
6183 \r
6184                 if ( bb == _T('\0') )\r
6185                         { return  aa; }\r
6186 \r
6187                 if ( aa != bb )\r
6188                         { return  aa - bb; }\r
6189 \r
6190                 a += 1;\r
6191                 b += 1;\r
6192         }\r
6193 }\r
6194 \r
6195 \r
6196  \r
6197 /***********************************************************************\r
6198   <<< [StrT_cmp_i_part] >>> \r
6199 ************************************************************************/\r
6200 int  StrT_cmp_i_part( const TCHAR* in_StringA_Start, const TCHAR* in_StringA_Over,\r
6201         const TCHAR* in_StringB )\r
6202 {\r
6203         const TCHAR*  a;\r
6204         const TCHAR*  b;\r
6205         TCHAR  aa;\r
6206         TCHAR  bb;\r
6207 \r
6208         a = in_StringA_Start;\r
6209         b = in_StringB;\r
6210 \r
6211         for (;;) {\r
6212                 if ( a >= in_StringA_Over ) {\r
6213                         bb = *b;\r
6214                         if ( bb == _T('\0') )\r
6215                                 { return  0; }\r
6216                         else\r
6217                                 { return  -bb; }\r
6218                 }\r
6219 \r
6220                 aa = *a;\r
6221                 bb = *b;\r
6222 \r
6223                 if ( bb == _T('\0') )\r
6224                         { return  aa; }\r
6225 \r
6226                 if ( aa != bb ) {\r
6227                         if ( _totlower( aa ) != _totlower( bb ) )\r
6228                                 { return  aa - bb; }\r
6229                 }\r
6230 \r
6231                 a += 1;\r
6232                 b += 1;\r
6233         }\r
6234 }\r
6235 \r
6236 \r
6237  \r
6238 /***********************************************************************\r
6239   <<< [StrT_cmp_part2] >>> \r
6240 ************************************************************************/\r
6241 int  StrT_cmp_part2( const TCHAR* in_StringA_Start, const TCHAR* in_StringA_Over,\r
6242         const TCHAR* in_StringB_Start, const TCHAR* in_StringB_Over )\r
6243 {\r
6244         int  length_A = in_StringA_Over - in_StringA_Start;\r
6245         int  length_B = in_StringB_Over - in_StringB_Start;\r
6246 \r
6247         if ( length_A != length_B ) {\r
6248                 return  length_A - length_B;\r
6249         }\r
6250         else {\r
6251                 return  _tcsncmp( in_StringA_Start, in_StringB_Start, length_A );\r
6252         }\r
6253 }\r
6254 \r
6255 \r
6256  \r
6257 /***********************************************************************\r
6258   <<< [StrT_refFName] >>> \r
6259 ************************************************************************/\r
6260 TCHAR*  StrT_refFName( const TCHAR* s )\r
6261 {\r
6262         const TCHAR*  p;\r
6263         TCHAR  c;\r
6264 \r
6265         p = StrT_chr( s, _T('\0') );\r
6266 \r
6267         if ( p == s )  return  (TCHAR*) s;\r
6268 \r
6269         for ( p--; p>s; p-- ) {\r
6270                 c = *p;\r
6271                 if ( c == _T('\\') || c == _T('/') )  return  (TCHAR*) p+1;\r
6272         }\r
6273         if ( *p == _T('\\') || *p == _T('/') )  return  (TCHAR*) p+1;\r
6274 \r
6275         return  (TCHAR*) s;\r
6276 }\r
6277  \r
6278 /***********************************************************************\r
6279   <<< [StrT_refExt] >>> \r
6280 ************************************************************************/\r
6281 TCHAR*  StrT_refExt( const TCHAR* s )\r
6282 {\r
6283         const TCHAR*  p;\r
6284 \r
6285         p = StrT_chr( s, _T('\0') );\r
6286 \r
6287         if ( p == s )  { return  (TCHAR*) s; }\r
6288 \r
6289         for ( p--; p>s; p-- ) {\r
6290                 if ( *p == _T('.') )  return  (TCHAR*) p+1;\r
6291                 if ( *p == _T('/') || *p == _T('\\') )\r
6292                         { return  (TCHAR*) StrT_chr( p, _T('\0') ); }\r
6293         }\r
6294         if ( *p == _T('.') )  return  (TCHAR*) p+1;\r
6295 \r
6296         return  (TCHAR*) StrT_chr( s, _T('\0') );\r
6297 }\r
6298 \r
6299 \r
6300  \r
6301 /***********************************************************************\r
6302 * Function: StrT_cutFragmentInPath\r
6303 ************************************************************************/\r
6304 void  StrT_cutFragmentInPath( TCHAR* in_out_Path )\r
6305 {\r
6306         TCHAR*  p;\r
6307 \r
6308         p = _tcschr( in_out_Path, _T('#') );\r
6309         if ( p != NULL ) {\r
6310                 *p = _T('\0');\r
6311         }\r
6312 }\r
6313 \r
6314 \r
6315  \r
6316 /***********************************************************************\r
6317   <<< [StrT_searchPartStringIndex] >>> \r
6318 ************************************************************************/\r
6319 int  StrT_searchPartStringIndex( const TCHAR* in_String, const TCHAR* in_StringOver,\r
6320         const TCHAR** in_StringsArray,  uint_fast32_t in_StringsArrayLength,\r
6321         int in_DefaultIndex )\r
6322 {\r
6323         const TCHAR**  p;\r
6324         const TCHAR**  p_over = in_StringsArray + in_StringsArrayLength;\r
6325         size_t         size = (byte_t*) in_StringOver - (byte_t*) in_String;\r
6326 \r
6327         for ( p = in_StringsArray;  p < p_over;  p += 1 ) {\r
6328                 if ( memcmp( *p, in_String, size ) == 0 ) {\r
6329                         return  p - in_StringsArray;\r
6330                 }\r
6331         }\r
6332         return  in_DefaultIndex;\r
6333 }\r
6334 \r
6335  \r
6336 /***********************************************************************\r
6337   <<< [StrT_searchPartStringIndexI] >>> \r
6338  - This ignores case sensitive.\r
6339 ************************************************************************/\r
6340 int  StrT_searchPartStringIndexI( const TCHAR* in_String, const TCHAR* in_StringOver,\r
6341         const TCHAR** in_StringsArray,  uint_fast32_t in_StringsArrayLength,\r
6342         int in_DefaultIndex )\r
6343 {\r
6344         const TCHAR**  p;\r
6345         const TCHAR**  p_over = in_StringsArray + in_StringsArrayLength;\r
6346         size_t         count = (TCHAR*) in_StringOver - (TCHAR*) in_String;\r
6347 \r
6348         for ( p = in_StringsArray;  p < p_over;  p += 1 ) {\r
6349                 if ( _tcsnicmp( *p, in_String, count ) == 0 ) {\r
6350                         return  p - in_StringsArray;\r
6351                 }\r
6352         }\r
6353         return  in_DefaultIndex;\r
6354 }\r
6355 \r
6356  \r
6357 /***********************************************************************\r
6358   <<< [StrT_convStrToId] >>> \r
6359 ************************************************************************/\r
6360 int  StrT_convStrToId( const TCHAR* str, const TCHAR** strs, const int* ids,\r
6361         int n, int default_id )\r
6362 {\r
6363         const TCHAR**  p;\r
6364         const TCHAR**  p_over = strs + n;\r
6365 \r
6366         for ( p = strs;  p < p_over;  p++ ) {\r
6367                 if ( _tcsicmp( *p, str ) == 0 )  return  ids[p - strs];\r
6368         }\r
6369         return  default_id;\r
6370 }\r
6371 \r
6372  \r
6373 /***********************************************************************\r
6374   <<< [StrT_convStrLeftToId] >>> \r
6375 ************************************************************************/\r
6376 int  StrT_convStrLeftToId( const TCHAR* Str, const TCHAR** Strs, const size_t* Lens, const int* Ids,\r
6377                            int CountOfStrs, TCHAR* Separeters, int DefaultId, TCHAR** out_PosOfLastOfStr )\r
6378 {\r
6379         const TCHAR**  pp;\r
6380         const TCHAR**  pp_over = Strs + CountOfStrs;\r
6381         const size_t*  p_len;\r
6382         const int*     p_id;\r
6383         const TCHAR*   p_last_of_str;\r
6384         TCHAR          c;\r
6385 \r
6386         p_len = Lens;\r
6387         p_id  = Ids;\r
6388         for ( pp = Strs;  pp < pp_over;  pp += 1 ) {\r
6389 \r
6390                 ASSERT_D( _tcslen( *pp ) == *p_len, goto err );\r
6391 \r
6392                 if ( _tcsncmp( Str, *pp, *p_len ) == 0 ) {\r
6393                         p_last_of_str = Str + *p_len;\r
6394                         c = *p_last_of_str;\r
6395                         if ( c == _T('\0') || _tcschr( Separeters, c ) != NULL ) {\r
6396                                 *out_PosOfLastOfStr = (TCHAR*) p_last_of_str;\r
6397                                 return  *p_id;\r
6398                         }\r
6399                 }\r
6400                 p_len += 1;\r
6401                 p_id += 1;\r
6402         }\r
6403         return  DefaultId;\r
6404 \r
6405 #if ! NDEBUG\r
6406  err:  return  DefaultId;\r
6407 #endif\r
6408 }\r
6409 \r
6410  \r
6411 /***********************************************************************\r
6412   <<< [StrT_replace] >>> \r
6413 ************************************************************************/\r
6414 errnum_t  StrT_replace( TCHAR* Out, size_t OutSize, const TCHAR* In,\r
6415                         const TCHAR* FromStr, const TCHAR* ToStr, unsigned Opt )\r
6416 {\r
6417         errnum_t        e;\r
6418         unsigned        from_size = _tcslen( FromStr ) * sizeof(TCHAR);\r
6419         unsigned        to_size   = _tcslen( ToStr )   * sizeof(TCHAR);\r
6420         const TCHAR*    p_in      = In;\r
6421         TCHAR*          p_out     = Out;\r
6422         const TCHAR*    p_in_from;\r
6423         size_t          copy_size;\r
6424         int             out_size  = OutSize - 1;\r
6425 \r
6426 \r
6427         /* \92u\8a·\82µ\82Ä\8f¬\82³\82­\82È\82é\82Æ\82«\82Í\81A\8d\82©\82ç\89E\82Ö\91\96\8d¸\82·\82é */\r
6428         if ( to_size <= from_size ) {\r
6429 \r
6430                 for (;;) {\r
6431 \r
6432                         /* In \82Ì\92\86\82Ì FromStr \82Ì\90æ\93ª\88Ê\92u\82ð p_in_from \82Ö */\r
6433                         p_in_from = _tcsstr( p_in, FromStr );\r
6434                         if ( p_in_from == NULL ) break;\r
6435 \r
6436                         /* In \82Ì\92\86\82Ì FromStr \82Ì\91O\82Ü\82Å In \82©\82ç Out \82Ö\83R\83s\81[\82·\82é */\r
6437                         copy_size = (char*)p_in_from - (char*)p_in;\r
6438                         out_size -= copy_size + to_size;\r
6439                         IF( out_size < 0 ) goto err_fa;\r
6440 \r
6441                         if ( p_out != p_in )\r
6442                                 memcpy( p_out, p_in, copy_size );\r
6443                         p_in  = (TCHAR*)( (char*)p_in  + copy_size );\r
6444                         p_out = (TCHAR*)( (char*)p_out + copy_size );\r
6445 \r
6446                         /* FromStr \82ð ToStr \82É\92u\82«\8a·\82¦\82é */\r
6447                         memcpy( p_out, ToStr, to_size );\r
6448                         p_in  = (TCHAR*)( (char*)p_in  + from_size );\r
6449                         p_out = (TCHAR*)( (char*)p_out + to_size );\r
6450 \r
6451                         /* "STR_1TIME" */\r
6452                         if ( Opt & STR_1TIME )\r
6453                                 { break; }\r
6454                 }\r
6455 \r
6456                 /* \8ec\82è\82ð In \82©\82ç Out \82Ö\83R\83s\81[\82·\82é */\r
6457                 #pragma warning(push)\r
6458                 #pragma warning(disable:4996)\r
6459                         if ( p_out != p_in )\r
6460                                 _tcscpy( p_out, p_in );\r
6461                         p_out = NULL;\r
6462                 #pragma warning(pop)\r
6463         }\r
6464 \r
6465 \r
6466         /* \92u\8a·\82µ\82Ä\91å\82«\82­\82È\82é\82Æ\82«\82Í\81A\89E\82©\82ç\8d\82Ö\91\96\8d¸\82·\82é */\r
6467         else {\r
6468 \r
6469                 /* In \82Ì\92\86\82Ì FromStr \82ª\96³\82¢\82Æ\82«\82Í\91S\95\94\83R\83s\81[\82·\82é */\r
6470                 p_in_from = _tcsstr( p_in, FromStr );\r
6471                 if ( p_in_from == NULL ) {\r
6472                         if ( p_out != p_in )\r
6473                                 StrT_cpy( Out, OutSize, In );\r
6474                         p_out = NULL;\r
6475                 }\r
6476                 else {\r
6477                         Set2a          froms;\r
6478                         TCHAR*         froms_X[10];\r
6479                         const TCHAR**  pp_froms;\r
6480                         size_t         plus_from_to;\r
6481 \r
6482                         Set2a_initConst( &froms, froms_X );\r
6483                         e= Set2a_init( &froms, froms_X, sizeof(froms_X) ); IF(e)goto fin2;\r
6484 \r
6485 \r
6486                         /* In \82Ì\92\86\82Ì FromStr \82Ì\91O\82Ü\82Å\83R\83s\81[\82·\82é */\r
6487                         copy_size = (char*)p_in_from - (char*)p_in;\r
6488                         out_size -= copy_size;\r
6489                         IF( out_size < 0 ) goto err_fa2;\r
6490 \r
6491                         memcpy( p_out, p_in, copy_size );\r
6492                         // p_in  = (TCHAR*)( (char*)p_in  + copy_size );  // \8cã\82Å\8eg\82í\82ê\82È\82¢\r
6493                         p_out = (TCHAR*)( (char*)p_out + copy_size );\r
6494 \r
6495 \r
6496                         /* In \82Ì\92\86\82Ì FromStr \82Ì\88Ê\92u\82ð froms \82Ö\8fW\82ß\82é */\r
6497                         for (;;) {\r
6498 \r
6499                                 e= Set2a_expandIfOverByAddr( &froms, froms_X, (TCHAR**)froms.Next + 1 ); IF(e)goto fin2;\r
6500                                 pp_froms = (const TCHAR**)froms.Next;  froms.Next = (void*)( pp_froms + 1 );\r
6501 \r
6502                                 *pp_froms =  p_in_from;\r
6503 \r
6504                                 if ( Opt & STR_1TIME )\r
6505                                         { break; }\r
6506 \r
6507                                 p_in = (const TCHAR*)( (char*)p_in_from + from_size );\r
6508                                 p_in_from = _tcsstr( p_in, FromStr );\r
6509                                 if ( p_in_from == NULL )  break;\r
6510                         }\r
6511 \r
6512                         plus_from_to = ( (TCHAR**)froms.Next - (TCHAR**)froms.First ) * (to_size - from_size);\r
6513 \r
6514 \r
6515                         /* In \82Ì\96\96\94ö\82Ì '\0' \82Ì\88Ê\92u\82à froms \82Ö */\r
6516                         e= Set2a_expandIfOverByAddr( &froms, froms_X, (TCHAR**)froms.Next + 1 ); IF(e)goto fin2;\r
6517                         pp_froms = (const TCHAR**)froms.Next;  froms.Next = (void*)( pp_froms + 1 );\r
6518                         p_in = StrT_chr( p_in, _T('\0') );\r
6519                         *pp_froms = p_in;\r
6520 \r
6521                         copy_size = ( (char*)p_in - (char*)In ) + plus_from_to;\r
6522                         IF( copy_size >= OutSize ) goto err_fa2;\r
6523                         p_out = (TCHAR*)( (char*)Out + copy_size );\r
6524                         plus_from_to -= to_size - from_size;\r
6525 \r
6526 \r
6527                         /* \89E\82©\82ç\8d\82Ö\91\96\8d¸\82·\82é */\r
6528                         for ( pp_froms = (TCHAR**)froms.Next - 1;\r
6529                               pp_froms > (TCHAR**)froms.First;\r
6530                               pp_froms -- ) {\r
6531 \r
6532                                 const TCHAR*  p_in_from       = *(pp_froms - 1);\r
6533                                 const TCHAR*  p_in_other      = (const TCHAR*)( (char*)p_in_from + from_size );\r
6534                                 const TCHAR*  p_in_other_over = *pp_froms;\r
6535                                       TCHAR*  p_out_to        = (TCHAR*)( (char*)Out + ( (char*)p_in_from - (char*)In ) + plus_from_to );\r
6536                                       TCHAR*  p_out_other     = (TCHAR*)( (char*)p_out_to + to_size );\r
6537 \r
6538                                 memmove( p_out_other, p_in_other, (char*)p_in_other_over - (char*)p_in_other );\r
6539                                 memcpy( p_out_to, ToStr, to_size );\r
6540 \r
6541                                 plus_from_to -= to_size - from_size;\r
6542                         }\r
6543 \r
6544                         goto fin2;\r
6545                 err_fa2:  e = E_FEW_ARRAY;   goto fin2;\r
6546                 fin2:\r
6547                         e= Set2a_finish( &froms, froms_X, e );\r
6548                         if ( e ) goto fin;\r
6549                 }\r
6550         }\r
6551 \r
6552         e=0;\r
6553 fin:\r
6554         if ( p_out != NULL )  *p_out = _T('\0');\r
6555         return  e;\r
6556 \r
6557 err_fa:  e = E_FEW_ARRAY;  goto fin;\r
6558 }\r
6559 \r
6560 \r
6561  \r
6562 /***********************************************************************\r
6563   <<< [StrT_replace1] >>> \r
6564 ************************************************************************/\r
6565 errnum_t  StrT_replace1( TCHAR* in_out_String, TCHAR FromCharacter, TCHAR ToCharacter,\r
6566         unsigned Opt )\r
6567 {\r
6568         TCHAR*  p;\r
6569 \r
6570         UNREFERENCED_VARIABLE( Opt );\r
6571 \r
6572         IF ( FromCharacter == _T('\0') )  { return  E_OTHERS; }\r
6573 \r
6574         p = in_out_String;\r
6575         for (;;) {\r
6576                 p = _tcschr( p, FromCharacter );\r
6577                 if ( p == NULL )  { break; }\r
6578                 *p = ToCharacter;\r
6579                 p += 1;\r
6580         }\r
6581 \r
6582         return  0;\r
6583 }\r
6584 \r
6585 \r
6586  \r
6587 /***********************************************************************\r
6588   <<< [StrT_trim] >>> \r
6589 ************************************************************************/\r
6590 errnum_t  StrT_trim( TCHAR* out_Str, size_t out_Str_Size, const TCHAR* in_Str )\r
6591 {\r
6592         const TCHAR*  p1;\r
6593         const TCHAR*  p2;\r
6594         TCHAR   c;\r
6595 \r
6596         p1 = in_Str;  while ( *p1 == _T(' ') || *p1 == _T('\t') )  p1++;\r
6597         for ( p2 = StrT_chr( p1, _T('\0') ) - 1;  p2 >= p1;  p2-- ) {\r
6598                 c = *p2;\r
6599                 if ( c != _T(' ') && c != _T('\t') && c != _T('\n') && c != _T('\r') )\r
6600                         break;\r
6601         }\r
6602         return  stcpy_part_r( out_Str, out_Str_Size, out_Str, NULL, p1, p2+1 );\r
6603 }\r
6604 \r
6605 \r
6606  \r
6607 /***********************************************************************\r
6608   <<< [StrT_cutPart] >>> \r
6609 ************************************************************************/\r
6610 errnum_t  StrT_cutPart( TCHAR*  in_out_String,  TCHAR*  in_StartOfCut,  TCHAR*  in_OverOfCut )\r
6611 {\r
6612         errnum_t  e;\r
6613         TCHAR*    over_of_cut = StrT_chr( in_StartOfCut, _T('\0') );\r
6614 \r
6615 #ifndef  NDEBUG\r
6616         TCHAR*    over_of_string = StrT_chr( in_out_String, _T('\0') );\r
6617 \r
6618         ASSERT_D( over_of_cut == over_of_string,   e=E_OTHERS; goto fin );\r
6619         ASSERT_D( in_StartOfCut >= in_out_String,   e=E_OTHERS; goto fin );\r
6620         ASSERT_D( in_StartOfCut <= over_of_string,  e=E_OTHERS; goto fin );\r
6621         ASSERT_D( in_OverOfCut  >= in_out_String,   e=E_OTHERS; goto fin );\r
6622         ASSERT_D( in_OverOfCut  <= over_of_string,  e=E_OTHERS; goto fin );\r
6623         ASSERT_D( in_StartOfCut <= in_OverOfCut,    e=E_OTHERS; goto fin );\r
6624 #endif\r
6625         UNREFERENCED_VARIABLE( in_out_String );\r
6626 \r
6627         memmove( in_StartOfCut,  in_OverOfCut,\r
6628                 PointerType_diff( over_of_cut + 1,  in_OverOfCut ) );\r
6629 \r
6630         e=0;\r
6631 #ifndef  NDEBUG\r
6632 fin:\r
6633 #endif\r
6634         return  e;\r
6635 }\r
6636 \r
6637 \r
6638  \r
6639 /***********************************************************************\r
6640   <<< [StrT_cutLastOf] >>> \r
6641 ************************************************************************/\r
6642 errnum_t  StrT_cutLastOf( TCHAR* in_out_Str, TCHAR Charactor )\r
6643 {\r
6644         TCHAR*  last = StrT_chr( in_out_Str, _T('\0') );\r
6645 \r
6646         if ( last > in_out_Str ) {\r
6647                 if ( *( last - 1 ) == Charactor )\r
6648                         { *( last - 1 ) = _T('\0'); }\r
6649         }\r
6650         return  0;\r
6651 }\r
6652 \r
6653 \r
6654  \r
6655 /***********************************************************************\r
6656   <<< [StrT_cutLineComment] >>> \r
6657 ************************************************************************/\r
6658 errnum_t  StrT_cutLineComment( TCHAR* out_Str, size_t out_Str_Size, const TCHAR* in_Str, const TCHAR* CommentSign )\r
6659 {\r
6660         const TCHAR*  p1;\r
6661         const TCHAR*  p2;\r
6662         TCHAR   c;\r
6663 \r
6664         p1 = in_Str;  while ( *p1 == _T(' ') || *p1 == _T('\t') )  p1++;\r
6665 \r
6666         p2 = _tcsstr( p1, CommentSign );\r
6667         if ( p2 == NULL )  p2 = StrT_chr( p1, _T('\0') );\r
6668 \r
6669         for ( p2 = p2 - 1;  p2 >= p1;  p2-- ) {\r
6670                 c = *p2;\r
6671                 if ( c != _T(' ') && c != _T('\t') && c != _T('\n') && c != _T('\r') )\r
6672                         break;\r
6673         }\r
6674         return  stcpy_part_r( out_Str, out_Str_Size, out_Str, NULL, p1, p2+1 );\r
6675 }\r
6676 \r
6677 \r
6678  \r
6679 /***********************************************************************\r
6680   <<< [StrT_insert] >>> \r
6681 ************************************************************************/\r
6682 errnum_t  StrT_insert( TCHAR*  in_out_WholeString,  size_t  in_MaxSize_of_WholeString,\r
6683         TCHAR*  in_out_Target_in_WholeString,  TCHAR**  out_NextTarget_in_WholeString,\r
6684         const TCHAR*  in_InsertString )\r
6685 {\r
6686         errnum_t  e;\r
6687         TCHAR*    over_of_whole_string = StrT_chr( in_out_WholeString, _T('\0') );\r
6688         size_t    insert_length = _tcslen( in_InsertString );\r
6689 \r
6690         ASSERT_D( in_out_Target_in_WholeString >= in_out_WholeString,   e=E_OTHERS; goto fin );\r
6691         ASSERT_D( in_out_Target_in_WholeString <= over_of_whole_string, e=E_OTHERS; goto fin );\r
6692 \r
6693         ASSERT_R( PointerType_diff( over_of_whole_string + 1,  in_out_WholeString ) + ( insert_length * sizeof(TCHAR) )\r
6694                 <= in_MaxSize_of_WholeString,  e=E_FEW_ARRAY; goto fin );\r
6695 \r
6696         memmove( in_out_Target_in_WholeString + insert_length,  in_out_Target_in_WholeString,\r
6697                 PointerType_diff( over_of_whole_string + 1,  in_out_Target_in_WholeString ) );\r
6698 \r
6699         memcpy( in_out_Target_in_WholeString,  in_InsertString,  insert_length * sizeof(TCHAR) );\r
6700 \r
6701         if ( out_NextTarget_in_WholeString != NULL ) {\r
6702                 *out_NextTarget_in_WholeString = in_out_Target_in_WholeString + insert_length;\r
6703         }\r
6704 \r
6705         e=0;\r
6706 fin:\r
6707         return  e;\r
6708 }\r
6709 \r
6710 \r
6711  \r
6712 /***********************************************************************\r
6713   <<< [StrHS_insert] >>> \r
6714 ************************************************************************/\r
6715 errnum_t  StrHS_insert( TCHAR**  in_out_WholeString,\r
6716         int  in_TargetIndexInWholeString,  int*  out_NextWholeInWholeString,\r
6717         const TCHAR*  in_InsertString )\r
6718 {\r
6719         errnum_t  e;\r
6720         TCHAR*    string = *in_out_WholeString;\r
6721         size_t    target_length = _tcslen( string );\r
6722         size_t    insert_length = _tcslen( in_InsertString );\r
6723         size_t    max_size = _msize( string ) / sizeof( TCHAR );\r
6724         size_t    new_max_size = target_length + insert_length + 1;\r
6725         TCHAR*    next_target;\r
6726 \r
6727 \r
6728         if ( max_size < new_max_size ) {\r
6729                 TCHAR*  new_string = (TCHAR*) realloc( string,  new_max_size * sizeof( TCHAR ) );\r
6730 \r
6731                 IF ( new_string == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
6732                 max_size = new_max_size;\r
6733                 string = new_string;\r
6734         }\r
6735 \r
6736         e= StrT_insert( string,  max_size * sizeof( TCHAR ),\r
6737                 string + in_TargetIndexInWholeString,  &next_target,\r
6738                 in_InsertString ); IF(e){goto fin;}\r
6739 \r
6740         if ( out_NextWholeInWholeString != NULL ) {\r
6741                 *out_NextWholeInWholeString = next_target - string;\r
6742         }\r
6743 \r
6744         e=0;\r
6745 fin:\r
6746         *in_out_WholeString = string;\r
6747         return  e;\r
6748 }\r
6749 \r
6750 \r
6751  \r
6752 /***********************************************************************\r
6753   <<< [StrHS_printfPartV] >>> \r
6754 ************************************************************************/\r
6755 errnum_t  StrHS_printfPartV( TCHAR**  in_out_String,\r
6756         int  in_IndexInString,  int*  out_NextIndexInString,\r
6757         const TCHAR*  in_Format,  va_list  in_VaList )\r
6758 {\r
6759         enum { first_max_size = 40 };\r
6760         enum { size_times = 4 };\r
6761 \r
6762         errnum_t  e;\r
6763         size_t    max_size;\r
6764         TCHAR*    string = *in_out_String;\r
6765 \r
6766 \r
6767         if ( string == NULL ) {\r
6768                 max_size = 0;\r
6769 \r
6770                 ASSERT_R( in_IndexInString == 0,  e=E_OTHERS; goto fin );\r
6771         }\r
6772         else {\r
6773                 max_size = _msize( string ) / sizeof( TCHAR );\r
6774 \r
6775                 ASSERT_R( in_IndexInString >= 0  &&  (size_t) in_IndexInString < max_size,\r
6776                         e=E_OTHERS; goto fin );\r
6777                 ASSERT_D( (size_t) in_IndexInString <= _tcslen( string ), __noop() );\r
6778         }\r
6779 \r
6780 \r
6781         if ( string == NULL ) {\r
6782                 string = (TCHAR*) malloc( first_max_size * sizeof( TCHAR ) );\r
6783                 max_size = first_max_size;\r
6784         }\r
6785 \r
6786 \r
6787         for (;;) {\r
6788 \r
6789                 #if _MSC_VER\r
6790                         #pragma warning(push)\r
6791                         #pragma warning(disable: 4996)\r
6792                 #endif\r
6793 \r
6794                 #ifdef  _UNICODE\r
6795                         int  r = _vsnwprintf( string + in_IndexInString,  max_size - in_IndexInString,\r
6796                                 in_Format,  in_VaList );\r
6797                 #else\r
6798                         int  r = _vsnprintf( string + in_IndexInString,  max_size - in_IndexInString,\r
6799                                 in_Format,  in_VaList );\r
6800                 #endif\r
6801 \r
6802                 #if _MSC_VER\r
6803                         #pragma warning(pop)\r
6804                 #endif\r
6805 \r
6806                 if ( r >= 0 ) {\r
6807                         if ( out_NextIndexInString != NULL ) {\r
6808                                 *out_NextIndexInString = in_IndexInString + r;\r
6809                         }\r
6810 \r
6811                         break;\r
6812                 }\r
6813 \r
6814                 {\r
6815                         size_t  new_max_size = max_size * size_times + first_max_size;\r
6816                         TCHAR*  new_string = (TCHAR*) realloc( string,  new_max_size * sizeof( TCHAR ) );\r
6817 \r
6818                         IF ( new_string == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
6819                         max_size = new_max_size;\r
6820                         string = new_string;\r
6821                 }\r
6822         }\r
6823 \r
6824         e=0;\r
6825 fin:\r
6826         *in_out_String = string;\r
6827         return  e;\r
6828 }\r
6829 \r
6830 \r
6831  \r
6832 /***********************************************************************\r
6833   <<< [StrHS_printfPart] >>> \r
6834 ************************************************************************/\r
6835 errnum_t  StrHS_printfPart( TCHAR**  in_out_String,\r
6836         int  in_IndexInString,  int*  out_NextIndexInString,\r
6837         const TCHAR*  in_Format,  ... )\r
6838 {\r
6839         errnum_t  e;\r
6840         va_list   va;\r
6841         va_start( va, in_Format );\r
6842 \r
6843         e = StrHS_printfPartV( in_out_String,  in_IndexInString,  out_NextIndexInString,  in_Format,  va );\r
6844 \r
6845         va_end( va );\r
6846         return  e;\r
6847 }\r
6848 \r
6849 \r
6850  \r
6851 /***********************************************************************\r
6852   <<< [StrHS_printfV] >>> \r
6853 ************************************************************************/\r
6854 errnum_t  StrHS_printfV( TCHAR**  in_out_String,\r
6855         const TCHAR*  in_Format,  va_list  in_VaList )\r
6856 {\r
6857         return  StrHS_printfPartV( in_out_String,  0,  NULL,  in_Format,  in_VaList );\r
6858 }\r
6859 \r
6860 \r
6861  \r
6862 /***********************************************************************\r
6863   <<< [StrHS_printf] >>> \r
6864 ************************************************************************/\r
6865 errnum_t  StrHS_printf( TCHAR**  in_out_String,\r
6866         const TCHAR*  in_Format,  ... )\r
6867 {\r
6868         errnum_t  e;\r
6869         va_list   va;\r
6870         va_start( va, in_Format );\r
6871 \r
6872         e = StrHS_printfPartV( in_out_String,  0,  NULL,  in_Format,  va );\r
6873 \r
6874         va_end( va );\r
6875         return  e;\r
6876 }\r
6877 \r
6878 \r
6879  \r
6880 /**************************************************************************\r
6881   <<< [StrT_meltCSV] >>> \r
6882 *************************************************************************/\r
6883 errnum_t  StrT_meltCSV( TCHAR* out_Str, size_t out_Str_Size, const TCHAR** pCSV )\r
6884 {\r
6885         errnum_t  e = 0;\r
6886         TCHAR*  t;\r
6887         TCHAR*  t_last = (TCHAR*)( (char*)out_Str + out_Str_Size - sizeof(TCHAR) );\r
6888         const TCHAR*  s;\r
6889         TCHAR  dummy[2];\r
6890         TCHAR  c;\r
6891 \r
6892         t = out_Str;\r
6893         s = *pCSV;\r
6894         if ( out_Str_Size <= 1 )  { t = dummy;  t_last = dummy; }\r
6895 \r
6896         if ( s == NULL ) { *t = _T('\0');  return 0; }\r
6897 \r
6898 \r
6899         /* \93ª\82Ì\8bó\94\92\82ð\8f\9c\82­ */\r
6900         while ( *s == _T(' ') || *s == _T('\t') )  s++;\r
6901 \r
6902         switch ( *s ) {\r
6903 \r
6904                 /* "" \82Å\88Í\82Ü\82ê\82Ä\82¢\82é\8fê\8d\87 */\r
6905                 case _T('"'):\r
6906                         s++;\r
6907                         c = *s;\r
6908                         while ( c != _T('"') || *(s+1) == _T('"') ) {  /* " \95\8e\9a\82Ü\82Å */\r
6909                                 if ( t == t_last ) { e = E_FEW_ARRAY;  t = dummy;  t_last = dummy + 1; }\r
6910                                 if ( c == *(s+1) && c == _T('"') )  s++;  /* " \95\8e\9a\8e©\91Ì */\r
6911                                 if ( c == _T('\0') )  break;\r
6912                                 *t = c;  t++;  s++;  c = *s;\r
6913                         }\r
6914                         *t = _T('\0');\r
6915 \r
6916                         s++;\r
6917                         for (;;) {\r
6918                                 if ( *s == _T(',') )  { s = s+1;  break; }\r
6919                                 if ( *s == _T('\0') ) { s = NULL;  break; }\r
6920                                 s++;\r
6921                         }\r
6922                         *pCSV = s;\r
6923                         return  e;\r
6924 \r
6925                 /* \8bó\82Ì\8d\80\96Ú\82Ì\8fê\8d\87 */\r
6926                 case ',':\r
6927                         *t = _T('\0');\r
6928                         *pCSV = s+1;\r
6929                         return  0;\r
6930 \r
6931                 case '\0':\r
6932                         *t = _T('\0');\r
6933                         *pCSV = NULL;\r
6934                         return  0;\r
6935 \r
6936                 /* "" \82Å\88Í\82Ü\82ê\82Ä\82¢\82È\82¢\8fê\8d\87 */\r
6937                 default: {\r
6938                         TCHAR*  sp = NULL;  /* \8dÅ\8cã\82Ì\98A\91±\82µ\82½\8bó\94\92\82Ì\90æ\93ª */\r
6939 \r
6940                         c = *s;\r
6941                         while ( c != _T(',') && c != _T('\0') && c != _T('\r') && c != _T('\n') ) {  /* , \95\8e\9a\82Ü\82Å */\r
6942 \r
6943                                 /* sp \82ð\90Ý\92è\82·\82é */\r
6944                                 if ( c == ' ' ) {\r
6945                                         if ( sp == NULL )  sp = t;\r
6946                                 }\r
6947                                 else  sp = NULL;\r
6948 \r
6949                                 if ( t == t_last ) { e = E_FEW_ARRAY;  t = dummy;  t_last = dummy + 1; }\r
6950 \r
6951                                 /* \83R\83s\81[\82·\82é */\r
6952                                 *t = c;  t++;  s++;  c = *s;\r
6953                         }\r
6954 \r
6955                         /* \95Ô\82è\92l\82ð\8c\88\92è\82·\82é */\r
6956                         if ( c == _T(',') )  s = s + 1;\r
6957                         else  s = NULL;\r
6958 \r
6959                         /* \96\96\94ö\82Ì\8bó\94\92\82ð\8eæ\82è\8f\9c\82­ */\r
6960                         if ( sp != NULL )  *sp = '\0';\r
6961                         else  *t = _T('\0');\r
6962 \r
6963                         *pCSV = s;\r
6964                         return  e;\r
6965                 }\r
6966         }\r
6967 }\r
6968 \r
6969 \r
6970  \r
6971 /***********************************************************************\r
6972   <<< [StrT_parseCSV_f] >>> \r
6973 ************************************************************************/\r
6974 errnum_t  StrT_parseCSV_f( const TCHAR* StringOfCSV, bit_flags32_t* out_ReadFlags, const TCHAR* Types, ... )\r
6975 {\r
6976         errnum_t       e;\r
6977         TCHAR          type;\r
6978         int            types_index;\r
6979         va_list        va;\r
6980         bool           is_next_omittable;\r
6981         bool           is_next_omit;\r
6982         const TCHAR*   column_pointer;\r
6983         TCHAR          a_char;\r
6984         TCHAR          column[ 32 ];\r
6985         bit_flags32_t  read_flags;\r
6986         bit_flags32_t  next_read_flag;\r
6987         TCHAR*         out_str;\r
6988         size_t         str_size = SIZE_MAX;  /* SIZE_MAX = Avoid warning */\r
6989 \r
6990 \r
6991         va_start( va, Types );\r
6992         types_index = 0;\r
6993         is_next_omittable = false;\r
6994         column_pointer = StringOfCSV;\r
6995         read_flags = 0;\r
6996         next_read_flag = 1;\r
6997         while ( column_pointer != NULL ) {\r
6998                 out_str = NULL;\r
6999 \r
7000                 type = Types[ types_index ];\r
7001                 switch ( type ) {\r
7002                         case  _T('\0'):\r
7003                                 goto exit_for;\r
7004 \r
7005                         case  _T('+'):\r
7006                                 is_next_omittable = true;\r
7007                                 break;\r
7008 \r
7009                         case  _T('s'):\r
7010                                 out_str = va_arg( va, TCHAR* );\r
7011                                 str_size = va_arg( va, size_t );\r
7012                                 ASSERT_D( str_size >= 1,  e=E_OTHERS; goto fin );\r
7013                                 break;\r
7014 \r
7015                         default:\r
7016                                 out_str = column;\r
7017                                 str_size = sizeof( column );\r
7018                                 break;\r
7019                 }\r
7020 \r
7021                 if ( out_str != NULL ) {\r
7022 \r
7023                         // Set "out_str" : Column string in CSV\r
7024                         column_pointer = StrT_skip( column_pointer, _T(" \t") );\r
7025                         a_char = *column_pointer;\r
7026                         if ( is_next_omittable  &&  ( a_char == _T('\0')  ||  a_char == _T(',') ) ) {\r
7027                                 column_pointer = StrT_chrs( column_pointer, _T(",") );\r
7028                                 if ( column_pointer != NULL ) { column_pointer += 1; }\r
7029                                 is_next_omit = true;\r
7030                         } else {\r
7031                                 e= StrT_meltCSV( out_str, str_size, &column_pointer ); IF(e){goto fin;}\r
7032 \r
7033                                 is_next_omit = false;\r
7034                                 read_flags |= next_read_flag;\r
7035                         }\r
7036 \r
7037                         switch ( type ) {\r
7038                                 case  _T('s'):\r
7039                                         /* "va_arg" was already called */\r
7040                                         break;\r
7041 \r
7042                                 case  _T('i'): {\r
7043                                         int*  pointer_of_int = va_arg( va, int* );\r
7044 \r
7045                                         if ( ! is_next_omit ) {\r
7046                                                 *pointer_of_int = ttoi_ex( column, 0 );\r
7047                                         }\r
7048                                         break;\r
7049                                 }\r
7050                                 case  _T('f'): {\r
7051                                         double*  pointer_of_double = va_arg( va, double* );\r
7052 \r
7053                                         if ( ! is_next_omit ) {\r
7054                                                 *pointer_of_double = _tstof( column );\r
7055                                         }\r
7056                                         break;\r
7057                                 }\r
7058                                 case  _T('b'): {\r
7059                                         bool*  pointer_of_bool = va_arg( va, bool* );\r
7060                                         int    strings_index;\r
7061                                         static const TCHAR*  strings[] = {\r
7062                                                 _T("1"), _T("true"), _T("yes"),\r
7063                                         };\r
7064 \r
7065                                         if ( ! is_next_omit ) {\r
7066                                                 *pointer_of_bool = false;\r
7067                                                 for ( strings_index = 0;\r
7068                                                         strings_index < _countof( strings );\r
7069                                                         strings_index += 1 )\r
7070                                                 {\r
7071                                                         if ( _tcsicmp( column, strings[ strings_index ] ) == 0 ) {\r
7072                                                                 *pointer_of_bool = true;\r
7073                                                                 break;\r
7074                                                         }\r
7075                                                 }\r
7076                                         }\r
7077                                         break;\r
7078                                 }\r
7079                                 case  _T('t'): {\r
7080                                         SYSTEMTIME*  pointer_of_time = va_arg( va, SYSTEMTIME* );\r
7081                                         int*         pointer_of_bias = va_arg( va, int* );\r
7082 \r
7083                                         if ( ! is_next_omit ) {\r
7084                                                 e= W3CDTF_toSYSTEMTIME( column, pointer_of_time, pointer_of_bias );\r
7085                                                         IF(e){goto fin;}\r
7086                                         }\r
7087                                         break;\r
7088                                 }\r
7089 \r
7090                                 default:\r
7091                                         ASSERT_R( false, e=E_OTHERS; goto fin );\r
7092                         }\r
7093 \r
7094                         is_next_omittable = false;\r
7095                         next_read_flag <<= 1;\r
7096                 }\r
7097 \r
7098                 types_index += 1;\r
7099         }\r
7100 exit_for:\r
7101         if ( out_ReadFlags != NULL ) {\r
7102                 *out_ReadFlags = read_flags;\r
7103         }\r
7104 \r
7105         e=0;\r
7106 fin:\r
7107         va_end( va );\r
7108         return  e;\r
7109 }\r
7110 \r
7111 \r
7112  \r
7113 /**************************************************************************\r
7114   <<< [StrT_changeToXML_Attribute] >>> \r
7115 *************************************************************************/\r
7116 errnum_t  StrT_changeToXML_Attribute( TCHAR* out_Str, size_t Str_Size, const TCHAR* InputStr )\r
7117 {\r
7118         errnum_t  e;\r
7119 \r
7120         e= StrT_replace( out_Str, Str_Size, InputStr, _T("&"),  _T("&amp;"),  0 ); IF(e)goto fin;\r
7121         e= StrT_replace( out_Str, Str_Size, out_Str,  _T("\""), _T("&quot;"), 0 ); IF(e)goto fin;\r
7122         e= StrT_replace( out_Str, Str_Size, out_Str,  _T("<"),  _T("&lt;"),   0 ); IF(e)goto fin;\r
7123 \r
7124         e=0;\r
7125 fin:\r
7126         return  e;\r
7127 }\r
7128 \r
7129 \r
7130  \r
7131 /**************************************************************************\r
7132   <<< [StrT_resumeFromXML_Attribute] >>> \r
7133 *************************************************************************/\r
7134 errnum_t  StrT_resumeFromXML_Attribute( TCHAR* out_Str, size_t Str_Size, const TCHAR* XML_Attr )\r
7135 {\r
7136         errnum_t  e;\r
7137 \r
7138         e= StrT_replace( out_Str, Str_Size, XML_Attr, _T("&quot;"), _T("\""), 0 ); IF(e)goto fin;\r
7139         e= StrT_replace( out_Str, Str_Size, out_Str,  _T("&lt;"),   _T("<"),  0 ); IF(e)goto fin;\r
7140         e= StrT_replace( out_Str, Str_Size, out_Str,  _T("&amp;"),  _T("&"),  0 ); IF(e)goto fin;\r
7141 \r
7142         e=0;\r
7143 fin:\r
7144         return  e;\r
7145 }\r
7146 \r
7147 \r
7148  \r
7149 /**************************************************************************\r
7150   <<< [StrT_changeToXML_Text] >>> \r
7151 *************************************************************************/\r
7152 errnum_t  StrT_changeToXML_Text( TCHAR* out_Str, size_t Str_Size, const TCHAR* InputStr )\r
7153 {\r
7154         errnum_t  e;\r
7155 \r
7156         e= StrT_replace( out_Str, Str_Size, InputStr, _T("&"), _T("&amp;"), 0 ); IF(e)goto fin;\r
7157         e= StrT_replace( out_Str, Str_Size, out_Str,  _T("<"), _T("&lt;"),  0 ); IF(e)goto fin;\r
7158         e= StrT_replace( out_Str, Str_Size, out_Str,  _T(">"), _T("&gt;"),  0 ); IF(e)goto fin;\r
7159 \r
7160         e=0;\r
7161 fin:\r
7162         return  e;\r
7163 }\r
7164 \r
7165 \r
7166  \r
7167 /***********************************************************************\r
7168   <<< [StrT_getExistSymbols] >>> \r
7169 ************************************************************************/\r
7170 errnum_t  StrT_getExistSymbols( unsigned* out, bool bCase, const TCHAR* Str, const TCHAR* Symbols, ... )\r
7171 {\r
7172         errnum_t  e;\r
7173         int       i;\r
7174         bool*   syms_exists = NULL;\r
7175         bool    b_nosym = false;\r
7176         TCHAR*  sym = NULL;\r
7177         size_t  sym_size = ( _tcslen( Symbols ) + 1 ) * sizeof(TCHAR);\r
7178         int     n_sym = 0;\r
7179         const TCHAR** syms = NULL;\r
7180         const TCHAR*  p;\r
7181 \r
7182         UNREFERENCED_VARIABLE( bCase );\r
7183 \r
7184         sym = (TCHAR*) malloc( sym_size ); IF(sym==NULL)goto err_fm;\r
7185 \r
7186 \r
7187         //=== Get Symbols\r
7188         p = Symbols;\r
7189         do {\r
7190                 e= StrT_meltCSV( sym, sym_size, &p ); IF(e)goto fin;\r
7191                 if ( sym[0] != _T('\0') )  n_sym ++;\r
7192         } while ( p != NULL );\r
7193 \r
7194         syms = (const TCHAR**) malloc( n_sym * sizeof(TCHAR*) ); IF(syms==NULL)goto err_fm;\r
7195         memset( (TCHAR**) syms, 0, n_sym * sizeof(TCHAR*) );\r
7196         syms_exists = (bool*) malloc( n_sym * sizeof(bool) ); IF(syms_exists==NULL)goto err_fm;\r
7197         memset( syms_exists, 0, n_sym * sizeof(bool) );\r
7198 \r
7199         p = Symbols;  i = 0;\r
7200         do {\r
7201                 e= StrT_meltCSV( sym, sym_size, &p ); IF(e)goto fin;\r
7202                 if ( sym[0] != _T('\0') ) {\r
7203                         e= MallocAndCopyString( &syms[i], sym ); IF(e)goto fin;\r
7204                         i++;\r
7205                 }\r
7206         } while ( p != NULL );\r
7207 \r
7208 \r
7209         //=== Check Str whether having Symbols\r
7210         p = Str;\r
7211         do {\r
7212                 e= StrT_meltCSV( sym, sym_size, &p ); IF(e)goto fin;\r
7213                 if ( sym[0] != _T('\0') ) {\r
7214                         for ( i = 0; i < n_sym; i++ ) {\r
7215                                 if ( _tcscmp( sym, syms[i] ) == 0 )  { syms_exists[i] = true;  break; }\r
7216                         }\r
7217                         if ( i == n_sym )  b_nosym = true;\r
7218                 }\r
7219         } while ( p != NULL );\r
7220 \r
7221 \r
7222         //=== Sum numbers\r
7223         {\r
7224                 va_list   va;\r
7225                 unsigned  num;\r
7226 \r
7227                 va_start( va, Symbols );\r
7228                 *out = 0;\r
7229                 for ( i = 0; i < n_sym; i++ ) {\r
7230                         num = va_arg( va, unsigned );\r
7231                         if ( syms_exists[i] )  *out |= num;\r
7232                 }\r
7233                 va_end( va );\r
7234         }\r
7235 \r
7236         e = ( b_nosym ? E_NOT_FOUND_SYMBOL : 0 );\r
7237 fin:\r
7238         if ( syms != NULL ) {\r
7239                 for ( i = 0; i < n_sym; i++ ) {\r
7240                         e= HeapMemory_free( &syms[i], e );\r
7241                 }\r
7242                 free( (TCHAR**) syms );\r
7243         }\r
7244         e= HeapMemory_free( &syms_exists, e );\r
7245         e= HeapMemory_free( &sym, e );\r
7246         return  e;\r
7247 err_fm: e= E_FEW_MEMORY; goto fin;\r
7248 }\r
7249 \r
7250  \r
7251 /**************************************************************************\r
7252   <<< [StrT_meltCmdLine] >>> \r
7253 *************************************************************************/\r
7254 errnum_t  StrT_meltCmdLine( TCHAR* out_Str, size_t out_Str_Size, const TCHAR** pLine )\r
7255 {\r
7256         errnum_t  e = 0;\r
7257         TCHAR*  t;\r
7258         TCHAR*  t_last = (TCHAR*)( (char*)out_Str + out_Str_Size - sizeof(TCHAR) );\r
7259         const TCHAR*  s;\r
7260         TCHAR  dummy;\r
7261         TCHAR  c;\r
7262 \r
7263         t = out_Str;\r
7264         s = *pLine;\r
7265         if ( out_Str_Size <= 1 )  { t = &dummy;  t_last = &dummy; }\r
7266 \r
7267         if ( s == NULL ) { *t = _T('\0');  return 0; }\r
7268 \r
7269 \r
7270         /* \93ª\82Ì\8bó\94\92\82ð\8f\9c\82­ */\r
7271         while ( *s == _T(' ') || *s == _T('\t') )  s++;\r
7272 \r
7273         switch ( *s ) {\r
7274 \r
7275                 /* "" \82Å\88Í\82Ü\82ê\82Ä\82¢\82é\8fê\8d\87 */\r
7276                 case _T('"'):\r
7277                         s++;\r
7278                         c = *s;\r
7279                         while ( c != _T('"') || *(s+1) == _T('"') ) {  /* " \95\8e\9a\82Ü\82Å */\r
7280                                 if ( t == t_last ) { e = E_FEW_ARRAY;  t = &dummy;  t_last = &dummy + 1; }\r
7281                                 if ( c == *(s+1) && c == _T('"') )  s++;  /* " \95\8e\9a\8e©\91Ì */\r
7282                                 if ( c == _T('\0') )  break;\r
7283                                 *t = c;  t++;  s++;  c = *s;\r
7284                         }\r
7285                         *t = _T('\0');\r
7286 \r
7287                         s++;\r
7288                         for (;;) {\r
7289                                 if ( *s == _T(' ') )  { s = s+1;  break; }\r
7290                                 if ( *s == _T('\0') ) { s = NULL;  break; }\r
7291                                 s++;\r
7292                         }\r
7293                         *pLine = s;\r
7294                         return  e;\r
7295 \r
7296                 case '\0':\r
7297                         *t = _T('\0');\r
7298                         *pLine = NULL;\r
7299                         return  0;\r
7300 \r
7301                 /* "" \82Å\88Í\82Ü\82ê\82Ä\82¢\82È\82¢\8fê\8d\87 */\r
7302                 default: {\r
7303                         c = *s;\r
7304                         while ( c != _T(' ') && c != _T('\0') && c != _T('\r') && c != _T('\n') ) {  /* \8bó\94\92\95\8e\9a\82Ü\82Å */\r
7305 \r
7306                                 if ( t == t_last ) { e = E_FEW_ARRAY;  t = &dummy;  t_last = &dummy + 1; }\r
7307 \r
7308                                 /* \83R\83s\81[\82·\82é */\r
7309                                 *t = c;  t++;  s++;  c = *s;\r
7310                         }\r
7311 \r
7312                         /* *pLine\82ð\8c\88\92è\82·\82é */\r
7313                         while ( *s == _T(' ') )  s = s + 1;\r
7314                         if ( *s == _T('\0') )  s = NULL;\r
7315 \r
7316                         /* \96\96\94ö */\r
7317                         *t = _T('\0');\r
7318 \r
7319                         *pLine = s;\r
7320                         return  e;\r
7321                 }\r
7322         }\r
7323 }\r
7324 \r
7325 \r
7326  \r
7327 /***********************************************************************\r
7328   <<< [W3CDTF_fromSYSTEMTIME] >>> \r
7329 ************************************************************************/\r
7330 errnum_t  W3CDTF_fromSYSTEMTIME( TCHAR* out_W3CDTF, size_t W3CDTF_ByteSize,\r
7331         const SYSTEMTIME* Time, int TimeZoneMinute )\r
7332 {\r
7333         errnum_t  e;\r
7334         TCHAR*    char_pointer = out_W3CDTF;\r
7335 \r
7336         e= stprintf_part_r( out_W3CDTF, W3CDTF_ByteSize, char_pointer, &char_pointer,\r
7337                 _T("%04d-%02d-%02dT%02d:%02d:%02d.%03d"),\r
7338                 Time->wYear, Time->wMonth,  Time->wDay,\r
7339                 Time->wHour, Time->wMinute, Time->wSecond, Time->wMilliseconds );\r
7340                 IF(e){goto fin;}\r
7341 \r
7342         e= W3CDTF_getTimeZoneDesignator( char_pointer,\r
7343                 GetStringSizeFromPointer( out_W3CDTF, W3CDTF_ByteSize, char_pointer ),\r
7344                 TimeZoneMinute ); IF(e){goto fin;}\r
7345 \r
7346         e=0;\r
7347 fin:\r
7348         return  e;\r
7349 }\r
7350 \r
7351 \r
7352  \r
7353 /***********************************************************************\r
7354   <<< [W3CDTF_toSYSTEMTIME] >>> \r
7355 ************************************************************************/\r
7356 errnum_t  W3CDTF_toSYSTEMTIME( const TCHAR* String, SYSTEMTIME* out_Time, int* out_BiasMinute )\r
7357 {\r
7358         errnum_t  e;\r
7359         size_t    string_length = _tcslen( String );\r
7360 \r
7361         /* 01234567890123456789012345678 */\r
7362         /*"yyyy-mm-ddThh:mm:ss.sss+00:00"*/\r
7363         /*"0000-00-00T00:00+00:00"*/\r
7364 \r
7365         IF_D( out_BiasMinute == NULL ) { e=E_OTHERS; goto fin; }\r
7366 \r
7367         /* With time */\r
7368         if ( string_length >= 11 ) {\r
7369                 TCHAR         a_char;\r
7370                 const TCHAR*  time_zone;\r
7371                 int           number;\r
7372 \r
7373                 IF ( String[10] != _T('T') ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7374                 IF ( String[4] != _T('-')  ||  String[7] != _T('-') )\r
7375                         { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7376 \r
7377                 IF ( string_length < 16 ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7378                 IF ( String[13] != _T(':') ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7379 \r
7380                 out_Time->wYear      = (WORD) _ttoi( &String[0] );\r
7381                 out_Time->wMonth     = (WORD) _ttoi( &String[5] );\r
7382                 out_Time->wDayOfWeek = 0;\r
7383                 out_Time->wDay       = (WORD) _ttoi( &String[8] );\r
7384                 out_Time->wHour      = (WORD) _ttoi( &String[11] );\r
7385                 out_Time->wMinute    = (WORD) _ttoi( &String[14] );\r
7386 \r
7387                 a_char = String[16];\r
7388                 if ( a_char == _T('+')  ||  a_char == _T('-')  ||  a_char == _T('Z') ) {\r
7389                         time_zone = &String[16];\r
7390                         out_Time->wSecond = 0;\r
7391                         out_Time->wMilliseconds = 0;\r
7392                 } else {\r
7393                         /* Second */\r
7394                         IF ( string_length < 19 ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7395                         IF ( a_char != _T(':') ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7396                         out_Time->wSecond = (WORD) _ttoi( &String[17] );\r
7397 \r
7398 \r
7399                         /* \8f¬\90\94\93_ */\r
7400                         a_char = String[19];\r
7401                         if ( a_char == _T('+')  ||  a_char == _T('-')  ||  a_char == _T('Z') ) {\r
7402                                 time_zone = &String[19];\r
7403                                 out_Time->wMilliseconds = 0;\r
7404                         }\r
7405                         else {\r
7406                                 IF ( a_char != _T('.') ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7407 \r
7408                                 out_Time->wMilliseconds = 0;\r
7409 \r
7410                                 number = String[20] - _T('0');\r
7411                                 if ( number < 0  ||  number > 9 ) {\r
7412                                         time_zone = &String[20];\r
7413                                 } else {\r
7414                                         out_Time->wMilliseconds += (WORD)( number * 100 );\r
7415 \r
7416                                         number = String[21] - _T('0');\r
7417                                         if ( number < 0  ||  number > 9 ) {\r
7418                                                 time_zone = &String[21];\r
7419                                         } else {\r
7420                                                 out_Time->wMilliseconds += (WORD)( number * 10 );\r
7421 \r
7422                                                 number = String[22] - _T('0');\r
7423                                                 if ( number < 0  ||  number > 9 ) {\r
7424                                                         time_zone = &String[22];\r
7425                                                 } else {\r
7426                                                         const TCHAR*  pointer = &String[23];\r
7427 \r
7428                                                         out_Time->wMilliseconds += (WORD)( number * 1 );\r
7429 \r
7430                                                         for (;;) {\r
7431                                                                 number = *pointer - _T('0');\r
7432                                                                 if ( number < 0  ||  number > 9 )\r
7433                                                                         { break; }\r
7434 \r
7435                                                                 pointer += 1;\r
7436                                                         }\r
7437                                                         time_zone = pointer;\r
7438                                                 }\r
7439                                         }\r
7440                                 }\r
7441 \r
7442                                 a_char = *time_zone;\r
7443                                 IF ( ! ( a_char == _T('+')  ||  a_char == _T('-')  ||  a_char == _T('Z') ) )\r
7444                                         { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7445                         }\r
7446                 }\r
7447 \r
7448                 /* Time zone */\r
7449                 if ( a_char == _T('Z') ) {\r
7450                         *out_BiasMinute = 0;\r
7451                 }\r
7452                 else {\r
7453                         size_t  time_zone_length = string_length - ( time_zone - String );\r
7454                         int     bias_minute;\r
7455 \r
7456                         IF ( time_zone_length < 6 ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7457                         IF ( time_zone[3] != _T(':') ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7458 \r
7459                         bias_minute = _ttoi( &time_zone[1] ) * 60 + _ttoi( &time_zone[4] );\r
7460                         if ( a_char == _T('-') ) { bias_minute = -bias_minute; }\r
7461                         *out_BiasMinute = bias_minute;\r
7462                 }\r
7463         }\r
7464 \r
7465         /* Without time */\r
7466         else {\r
7467                 out_Time->wDayOfWeek    = 0;\r
7468                 out_Time->wHour         = 0;\r
7469                 out_Time->wMinute       = 0;\r
7470                 out_Time->wSecond       = 0;\r
7471                 out_Time->wMilliseconds = 0;\r
7472                 *out_BiasMinute         = 0;\r
7473 \r
7474                 IF ( string_length < 4 ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7475 \r
7476                 /* Year */\r
7477                 out_Time->wYear = (WORD) _ttoi( &String[0] );\r
7478 \r
7479                 /* Month */\r
7480                 if ( string_length > 4 ) {\r
7481                         IF ( string_length < 7 ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7482                         IF ( String[4] != _T('-') ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7483                         out_Time->wMonth = (WORD) _ttoi( &String[5] );\r
7484                 } else {\r
7485                         out_Time->wMonth = 1;\r
7486                 }\r
7487 \r
7488                 /* Day */\r
7489                 if ( string_length > 7 ) {\r
7490                         IF ( string_length < 10 ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7491                         IF ( String[7] != _T('-') ) { e=E_NOT_FOUND_SYMBOL; goto fin; }\r
7492                         out_Time->wDay = (WORD) _ttoi( &String[8] );\r
7493                 } else {\r
7494                         out_Time->wDay = 1;\r
7495                 }\r
7496         }\r
7497 \r
7498         e=0;\r
7499 fin:\r
7500         return  e;\r
7501 }\r
7502 \r
7503 \r
7504  \r
7505 /***********************************************************************\r
7506   <<< [W3CDTF_getTimeZoneDesignator] >>> \r
7507 ************************************************************************/\r
7508 errnum_t  W3CDTF_getTimeZoneDesignator( TCHAR* out_TZD, size_t TZD_ByteSize,\r
7509         int  BiasMinute )\r
7510 {\r
7511         errnum_t  e;\r
7512         TCHAR     sign;\r
7513         TIME_ZONE_INFORMATION  time_zone;\r
7514 \r
7515 \r
7516         /* Set "BiasMinute" */\r
7517         if ( BiasMinute == W3CDTF_CURRENT_TIME_ZONE ) {\r
7518                 GetTimeZoneInformation( &time_zone );\r
7519                 BiasMinute = -time_zone.Bias;\r
7520         }\r
7521         else {\r
7522                 enum { minute_1day = 1440 };\r
7523 \r
7524                 IF_D ( BiasMinute < -minute_1day  ||  BiasMinute > minute_1day )\r
7525                         { e=E_OTHERS; goto fin; }\r
7526         }\r
7527 \r
7528 \r
7529         /* Set "sign" */\r
7530         if ( BiasMinute >= 0 ) {\r
7531                 sign = _T('+');\r
7532         } else {\r
7533                 sign = _T('-');\r
7534                 BiasMinute = -BiasMinute;\r
7535         }\r
7536 \r
7537 \r
7538         /* Set "out_TZD" */\r
7539         _stprintf_s( out_TZD, TZD_ByteSize / sizeof(TCHAR), _T("%c%02d:%02d"),\r
7540                 sign,  BiasMinute / 60,  BiasMinute % 60 );\r
7541 \r
7542         e=0;\r
7543 fin:\r
7544         return  e;\r
7545 }\r
7546 \r
7547 \r
7548  \r
7549 /***********************************************************************\r
7550   <<< [StrT_isFullPath] >>> \r
7551 ************************************************************************/\r
7552 bool  StrT_isFullPath( const TCHAR* path )\r
7553 {\r
7554         bool  ret;\r
7555 \r
7556         if ( path[0] == _T('\\')  &&  path[1] == _T('\\') ) {\r
7557                 ret = true;\r
7558         } else {\r
7559                 const TCHAR*  back_slash = _tcschr( path, _T('\\') );\r
7560                 const TCHAR*  slash = _tcschr( path, _T('/') );\r
7561                 const TCHAR*  colon = _tcschr( path, _T(':') );\r
7562 \r
7563                 if ( colon != NULL ) {\r
7564                         const TCHAR*  p;\r
7565 \r
7566                         for ( p = path;  p < colon;  p += 1 ) {\r
7567                                 if ( ! _istalnum( *p ) ) {\r
7568                                         colon = NULL;\r
7569                                         break;\r
7570                                 }\r
7571                         }\r
7572                 }\r
7573 \r
7574                 ret = ( colon != NULL ) &&\r
7575                         ( back_slash == colon + 1  ||  slash == colon + 1 );\r
7576         }\r
7577 \r
7578         return  ret;\r
7579 }\r
7580 \r
7581  \r
7582 /**************************************************************************\r
7583   <<< [StrT_getFullPath_part] >>> \r
7584 *************************************************************************/\r
7585 errnum_t  StrT_getFullPath_part( TCHAR* out_FullPath, size_t FullPathSize, TCHAR* OutStart,\r
7586         TCHAR** out_OutLast, const TCHAR* StepPath, const TCHAR* BasePath )\r
7587 {\r
7588         errnum_t      e;\r
7589         TCHAR         separator = (TCHAR) DUMMY_INITIAL_VALUE_TCHAR;\r
7590         const TCHAR*  separator_path;\r
7591         TCHAR*        out_full_path_over = (TCHAR*)( (uint8_t*) out_FullPath + FullPathSize );\r
7592         TCHAR*        null_position = NULL;\r
7593 \r
7594         #if  CHECK_ARG\r
7595                 /* "BasePath" must be out of "out_FullPath" */\r
7596                 ASSERT_R( BasePath < out_FullPath  ||\r
7597                         (uint8_t*) BasePath >= (uint8_t*) out_FullPath + FullPathSize,\r
7598                         goto err );\r
7599         #endif\r
7600 \r
7601 \r
7602         /* If "StepPath" == "", out_FullPath = "" */\r
7603         if ( StepPath[0] == _T('\0') ) {\r
7604                 ASSERT_R( FullPathSize >= sizeof(TCHAR), goto err_fm );\r
7605                 out_FullPath[0] = _T('\0');\r
7606                 e=0;  goto fin;\r
7607         }\r
7608 \r
7609 \r
7610         /* Set "OutStart" */\r
7611         if ( OutStart == NULL )\r
7612                 { OutStart = out_FullPath; }\r
7613 \r
7614 \r
7615         /* Set "separator" : \ or / from "BasePath" */\r
7616         if ( StrT_isFullPath( StepPath ) ) {\r
7617                 separator_path = StepPath;\r
7618         }\r
7619         else if ( BasePath == NULL ) {\r
7620                 separator = _T('\\');\r
7621                 separator_path = NULL;\r
7622         }\r
7623         else {\r
7624                 separator_path = BasePath;\r
7625         }\r
7626         if ( separator_path != NULL ) {\r
7627                 const TCHAR*    p;\r
7628                 const TCHAR*    p2;\r
7629 \r
7630                 p  = _tcschr( separator_path, _T('\\') );\r
7631                 p2 = _tcschr( separator_path, _T('/') );\r
7632                 if ( p == NULL ) {\r
7633                         if ( p2 == NULL )\r
7634                                 { separator = _T('\\'); }\r
7635                         else\r
7636                                 { separator = _T('/'); }\r
7637                 } else {\r
7638                         if ( p2 == NULL )\r
7639                                 { separator = _T('\\'); }\r
7640                         else {\r
7641                                 if ( p < p2 )\r
7642                                         { separator = _T('\\'); }\r
7643                                 else\r
7644                                         { separator = _T('/'); }\r
7645                         }\r
7646                 }\r
7647         }\r
7648 \r
7649 \r
7650         /* Set "OutStart" : "BasePath" + / + "StepPath" */\r
7651         if ( StrT_isFullPath( StepPath ) ) {\r
7652                 size_t  step_path_length = _tcslen( StepPath );\r
7653 \r
7654                 IF( OutStart + step_path_length >= out_full_path_over ) goto err_fa;\r
7655                 memmove( OutStart,  StepPath,  ( step_path_length + 1 ) * sizeof(TCHAR) );\r
7656 \r
7657                 /* Set "null_position" */\r
7658                 null_position = OutStart + step_path_length;\r
7659         }\r
7660         else {\r
7661                 TCHAR   c;\r
7662                 TCHAR*  p;\r
7663                 size_t  base_path_length;\r
7664                 size_t  step_path_length = _tcslen( StepPath );\r
7665 \r
7666                 if ( BasePath == NULL ) {\r
7667                         base_path_length = GetCurrentDirectory( 0, NULL ) - 1;\r
7668                 }\r
7669                 else {\r
7670                         base_path_length = _tcslen( BasePath );\r
7671                         c = BasePath[ base_path_length - 1 ];\r
7672                         if ( c == _T('\\')  ||  c == _T('/') )\r
7673                                 { base_path_length -= 1; }\r
7674                 }\r
7675 \r
7676                 p = OutStart + base_path_length + 1;\r
7677                 IF( p + step_path_length >= out_full_path_over ) goto err_fa;\r
7678                 memmove( p,  StepPath,  ( step_path_length + 1 ) * sizeof(TCHAR) );\r
7679                         /* memmove is for "out_FullPath" == "StepPath" */\r
7680 \r
7681                 if ( BasePath == NULL ) {\r
7682                         GetCurrentDirectory( base_path_length + 1, OutStart );\r
7683                         if ( OutStart[ base_path_length - 1 ] == _T('\\') )\r
7684                                 { base_path_length -= 1; }\r
7685                 } else {\r
7686                         memcpy( OutStart,  BasePath,  base_path_length * sizeof(TCHAR) );\r
7687                 }\r
7688                 OutStart[ base_path_length ] = separator;\r
7689 \r
7690 \r
7691                 /* Set "null_position" */\r
7692                 null_position = p + step_path_length;\r
7693         }\r
7694 \r
7695 \r
7696         /* Replace \ and / to "separator" in "OutStart" */\r
7697         {\r
7698                 TCHAR  other_separator;\r
7699 \r
7700                 if ( separator == _T('/') )\r
7701                         { other_separator = _T('\\'); }\r
7702                 else\r
7703                         { other_separator = _T('/'); }\r
7704 \r
7705                 e= StrT_replace1( OutStart, other_separator, separator, 0 ); IF(e)goto fin;\r
7706         }\r
7707 \r
7708 \r
7709         /* Replace \*\..\ to \ */\r
7710         {\r
7711                 enum  { length = 4 };\r
7712                 TCHAR   parent[ length + 1 ];  /* \..\ or /../ */\r
7713                 TCHAR*  parent_position;\r
7714                 TCHAR*  p;\r
7715 \r
7716                 parent[0] = separator;\r
7717                 parent[1] = _T('.');\r
7718                 parent[2] = _T('.');\r
7719                 parent[3] = separator;\r
7720                 parent[4] = _T('\0');\r
7721 \r
7722                 for (;;) {\r
7723                         parent_position = _tcsstr( OutStart, parent );\r
7724                         if ( parent_position == NULL )  { break; }\r
7725 \r
7726                         p = parent_position - 1;\r
7727                         for (;;) {\r
7728                                 IF( p < OutStart ) {goto err;}  /* "../" are too many */\r
7729                                 if ( *p == separator )  { break; }\r
7730                                 p -= 1;\r
7731                         }\r
7732 \r
7733                         memmove( p + 1,\r
7734                                 parent_position + length,\r
7735                                 ( null_position - ( parent_position + length ) + 1 ) * sizeof(TCHAR) );\r
7736 \r
7737                         null_position -= ( parent_position + length ) - ( p + 1 );\r
7738                 }\r
7739         }\r
7740 \r
7741 \r
7742         /* Cut last \*\.. */\r
7743         {\r
7744                 enum  { length = 3 };\r
7745                 TCHAR*  p;\r
7746 \r
7747                 while ( null_position - length >= OutStart ) {\r
7748                         if ( *( null_position - 3 ) != separator  ||\r
7749                              *( null_position - 2 ) != _T('.')  ||\r
7750                              *( null_position - 1 ) != _T('.') )\r
7751                                 { break; }\r
7752 \r
7753                         p = null_position - 4;\r
7754                         for (;;) {\r
7755                                 IF( p < OutStart ) {goto err;}  /* "../" are too many */\r
7756                                 if ( *p == separator )  { break; }\r
7757                                 p -= 1;\r
7758                         }\r
7759 \r
7760                         *p = _T('\0');\r
7761 \r
7762                         null_position = p;\r
7763                 }\r
7764         }\r
7765 \r
7766 \r
7767         /* Replace \.\ to \ */\r
7768         {\r
7769                 enum  { length = 3 };\r
7770                 TCHAR   current[ length + 1 ];  /* \.\ or /./ */\r
7771                 TCHAR*  current_position;\r
7772 \r
7773                 current[0] = separator;\r
7774                 current[1] = _T('.');\r
7775                 current[2] = separator;\r
7776                 current[3] = _T('\0');\r
7777 \r
7778                 for (;;) {\r
7779                         current_position = _tcsstr( OutStart, current );\r
7780                         if ( current_position == NULL )  { break; }\r
7781 \r
7782                         memmove( current_position + 1,\r
7783                                 current_position + length,\r
7784                                 ( null_position - ( current_position + length ) + 1 ) * sizeof(TCHAR) );\r
7785 \r
7786                         null_position -= length - 1;\r
7787                 }\r
7788         }\r
7789 \r
7790 \r
7791         /* Cut last \. */\r
7792         {\r
7793                 TCHAR*  over = StrT_chr( OutStart, _T('\0') );\r
7794 \r
7795                 while ( over - 2 >= OutStart  &&\r
7796                                 *( over - 1 ) == _T('.')  &&  *( over - 2 ) == separator ) {\r
7797                         over -= 2;\r
7798                         *over = _T('\0');\r
7799                 }\r
7800         }\r
7801 \r
7802 \r
7803         /* Add root / */\r
7804         if ( null_position - 1 >= OutStart ) {\r
7805                 if ( *( null_position - 1 ) == _T(':') ) {\r
7806                         IF( null_position + 1 >= out_full_path_over ) goto err_fa;\r
7807 \r
7808                         *( null_position + 0 ) = separator;\r
7809                         *( null_position + 1 ) = _T('\0');\r
7810                         null_position += 1;\r
7811                 }\r
7812         }\r
7813 \r
7814 \r
7815         /* Set "*out_OutLast" */\r
7816         if ( out_OutLast != NULL )\r
7817                 { *out_OutLast = null_position; }\r
7818 \r
7819         e=0;\r
7820 fin:\r
7821         return  e;\r
7822 \r
7823 err:     e = E_OTHERS;      goto fin;\r
7824 err_fa:  e = E_FEW_ARRAY;   goto fin;\r
7825 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
7826 }\r
7827 \r
7828 \r
7829  \r
7830 /***********************************************************************\r
7831   <<< [StrT_allocateFullPath] >>> \r
7832 ************************************************************************/\r
7833 errnum_t  StrT_allocateFullPath( TCHAR** out_FullPath, const TCHAR* StepPath, TCHAR* BasePath )\r
7834 {\r
7835         errnum_t  e;\r
7836         int  step_path_length = _tcslen( StepPath );\r
7837         int  base_path_length;\r
7838         int  full_path_size;\r
7839 \r
7840         if ( BasePath == NULL ) {\r
7841                 base_path_length = GetCurrentDirectory( 0, NULL ) - 1;\r
7842         } else {\r
7843                 base_path_length = _tcslen( BasePath );\r
7844         }\r
7845 \r
7846         full_path_size = ( step_path_length + 1 + base_path_length + 1 ) * sizeof(TCHAR);\r
7847 \r
7848         e= HeapMemory_allocateBytes( out_FullPath, full_path_size ); IF(e){goto fin;}\r
7849         e= StrT_getFullPath( *out_FullPath, full_path_size, StepPath, BasePath ); IF(e){goto fin;}\r
7850 \r
7851         e=0;\r
7852 fin:\r
7853         return  e;\r
7854 }\r
7855 \r
7856 \r
7857  \r
7858 /***********************************************************************\r
7859   <<< [StrT_getParentFullPath_part] >>> \r
7860 ************************************************************************/\r
7861 errnum_t  StrT_getParentFullPath_part( TCHAR* Str, size_t StrSize, TCHAR* StrStart,\r
7862         TCHAR** out_StrLast, const TCHAR* StepPath, const TCHAR* BasePath )\r
7863 {\r
7864         errnum_t  e;\r
7865         TCHAR*  p;\r
7866 \r
7867         IF_D( StrStart < Str ||  (char*) StrStart >= (char*)Str + StrSize ){goto err;}\r
7868 \r
7869         if ( StepPath[0] == _T('\0') ) {\r
7870                 *StrStart = _T('\0');\r
7871                 return  0;\r
7872         }\r
7873 \r
7874         /* \90â\91Î\83p\83X\82É\82·\82é */\r
7875         e= StrT_getFullPath( StrStart,\r
7876                 StrSize - ( (char*)StrStart - (char*)Str ),\r
7877                 StepPath, BasePath ); IF(e)goto fin;\r
7878 \r
7879 \r
7880         /* Cut last \ */\r
7881         p = StrT_chr( StrStart, _T('\0') );\r
7882         if ( p > StrStart ) {\r
7883                 TCHAR  c = *( p - 1 );\r
7884                 if ( c == _T('\\')  ||  c == _T('/') )\r
7885                         { *( p - 1 ) = _T('\0'); }\r
7886         }\r
7887 \r
7888 \r
7889         /* \90e\82Ö */\r
7890         p = StrT_refFName( StrStart );\r
7891         if ( p > StrStart )  p--;\r
7892         *p = _T('\0');\r
7893 \r
7894 \r
7895         /* \83\8b\81[\83g\82È\82ç \ \82ð\95t\82¯\82é */\r
7896         if ( p == StrStart + 2 ) {\r
7897                 *p = _T('\\');  p++;  *p = _T('\0');\r
7898         }\r
7899 \r
7900         if ( out_StrLast != NULL )  *out_StrLast = p;\r
7901 \r
7902         e=0;\r
7903 fin:\r
7904         return  e;\r
7905 \r
7906 err:  e = E_OTHERS;  goto fin;\r
7907 }\r
7908 \r
7909 \r
7910  \r
7911 /***********************************************************************\r
7912   <<< [StrT_isOverOfFileName] >>> \r
7913 - "" or "\" or "/"\r
7914 ************************************************************************/\r
7915 inline bool  StrT_isOverOfFileName( const TCHAR* PointerInPath )\r
7916 {\r
7917         return  PointerInPath == NULL  ||\r
7918                 *PointerInPath == _T('\0')  ||\r
7919                 ( ( *PointerInPath == _T('\\')  ||  *PointerInPath == _T('/') )  &&\r
7920                         *(PointerInPath + 1) == _T('\0') );\r
7921 }\r
7922 \r
7923 \r
7924  \r
7925 /***********************************************************************\r
7926   <<< [StrT_getStepPath] >>> \r
7927 ************************************************************************/\r
7928 errnum_t  StrT_getStepPath( TCHAR* out_StepPath, size_t StepPathSize,\r
7929         const TCHAR* FullPath, const TCHAR* BasePath )\r
7930 {\r
7931         errnum_t      e;\r
7932         const TCHAR*  abs_pointer;\r
7933         const TCHAR*  base_pointer;\r
7934         TCHAR         abs_char;\r
7935         TCHAR         base_char;\r
7936         TCHAR         separator;\r
7937         const TCHAR*  abs_separator_pointer  = (const TCHAR*) DUMMY_INITIAL_VALUE;\r
7938         const TCHAR*  base_separator_pointer = (const TCHAR*) DUMMY_INITIAL_VALUE;\r
7939         TCHAR*        step_pointer;\r
7940         TCHAR         parent_symbol[4] = { _T('.'), _T('.'), _T('\\'), _T('\0') };\r
7941         TCHAR         base_path_2[ MAX_PATH ];\r
7942 \r
7943 \r
7944         ASSERT_D( out_StepPath != FullPath, goto err );\r
7945 \r
7946         abs_pointer = FullPath;\r
7947 \r
7948 \r
7949         /* Set "base_pointer" */\r
7950         if ( BasePath == NULL ) {\r
7951                 base_pointer = _tgetcwd( base_path_2, _countof(base_path_2) );\r
7952                 IF( base_pointer == NULL ) {goto err;}\r
7953         }\r
7954         else {\r
7955                 base_pointer = BasePath;\r
7956         }\r
7957 \r
7958 \r
7959         /* Set "abs_separator_pointer", "base_separator_pointer" : after same parent folder path */\r
7960         separator = 0;\r
7961         for (;;) {  /* while abs_char == base_char */\r
7962                 abs_char  = *abs_pointer;\r
7963                 base_char = *base_pointer;\r
7964 \r
7965                 abs_char  = (TCHAR) _totlower( abs_char );\r
7966                 base_char = (TCHAR) _totlower( base_char );\r
7967 \r
7968                 if ( abs_char == _T('\0') ) {\r
7969 \r
7970                         /* out_StepPath = ".", if FullPath == BasePath */\r
7971                         if ( base_char == _T('\0') ) {\r
7972                                 e= StrT_cpy( out_StepPath, StepPathSize, _T(".") ); IF(e)goto fin;\r
7973                                 e=0; goto fin;\r
7974                         }\r
7975                         break;\r
7976                 }\r
7977                 if ( base_char == _T('\0') )  { break; }\r
7978 \r
7979                 if ( abs_char != base_char ) {\r
7980                         if ( ( abs_char  == _T('/')  ||  abs_char  == _T('\\') ) &&\r
7981                              ( base_char == _T('/')  ||  base_char == _T('\\') ) )\r
7982                                 { /* Do nothing */ }\r
7983                         else\r
7984                                 { break; }\r
7985                 }\r
7986 \r
7987                 /* Set "separator", "abs_separator_pointer", "base_separator_pointer" */\r
7988                 if (  base_char == _T('/')  ||  base_char == _T('\\')  ) {\r
7989                         if ( separator == 0 )\r
7990                                 { separator = base_char; }\r
7991 \r
7992                         abs_separator_pointer = abs_pointer;\r
7993                         base_separator_pointer = base_pointer;\r
7994                 }\r
7995 \r
7996                 abs_pointer  += 1;\r
7997                 base_pointer += 1;\r
7998         }\r
7999 \r
8000 \r
8001         /* FullPath \82Æ BasePath \82Ì\8aÖ\8cW\82ª\81A\95Ð\95û\82Ì\88ê\95\94\82ª\82à\82¤\95Ð\95û\82Ì\91S\91Ì\82Å\82 \82é\82Æ\82« */\r
8002         if ( ( ( abs_char == _T('/')  ||  abs_char == _T('\\') )  &&  base_char == _T('\0') ) ||\r
8003              (  base_char == _T('/')  || base_char == _T('\\') )  &&   abs_char == _T('\0') ) {\r
8004 \r
8005                 if ( separator == 0 )\r
8006                         { separator = abs_char; }\r
8007 \r
8008                 abs_separator_pointer = abs_pointer;\r
8009                 base_separator_pointer = base_pointer;\r
8010         }\r
8011 \r
8012 \r
8013         /* out_StepPath = FullPath, if there is not same folder */\r
8014         if ( separator == 0 ) {\r
8015                 e= StrT_cpy( out_StepPath, StepPathSize, FullPath ); IF(e)goto fin;\r
8016                 e=0; goto fin;\r
8017         }\r
8018 \r
8019 \r
8020         /* Add "..\" to "out_StepPath" */\r
8021         parent_symbol[2] = separator;\r
8022         step_pointer = out_StepPath;\r
8023         for (;;) {\r
8024                 const TCHAR*  p1;\r
8025                 const TCHAR*  p2;\r
8026 \r
8027                 if ( StrT_isOverOfFileName( base_separator_pointer ) )\r
8028                         { break; }\r
8029 \r
8030 \r
8031                 /* Set "base_separator_pointer" : next separator */\r
8032                 p1 = _tcschr( base_separator_pointer + 1, _T('/') );\r
8033                 p2 = _tcschr( base_separator_pointer + 1, _T('\\') );\r
8034 \r
8035                 if ( p1 == NULL ) {\r
8036                         if ( p2 == NULL )\r
8037                                 { base_separator_pointer = NULL; }\r
8038                         else\r
8039                                 { base_separator_pointer = p2; }\r
8040                 }\r
8041                 else {\r
8042                         if ( p2 == NULL ) {\r
8043                                 base_separator_pointer = p1;\r
8044                         } else {\r
8045                                 if ( p1 < p2 )\r
8046                                         { base_separator_pointer = p1; }\r
8047                                 else\r
8048                                         { base_separator_pointer = p2; }\r
8049                         }\r
8050                 }\r
8051 \r
8052 \r
8053                 /* Add "..\" to "out_StepPath" */\r
8054                 e= stcpy_part_r( out_StepPath, StepPathSize, step_pointer, &step_pointer,\r
8055                         parent_symbol, NULL ); IF(e)goto fin;\r
8056         }\r
8057 \r
8058 \r
8059         /* Copy a part of "FullPath" to "out_StepPath" */\r
8060         if ( StrT_isOverOfFileName( abs_separator_pointer ) ) {\r
8061                 ASSERT_D( step_pointer > out_StepPath, goto err );\r
8062                 *( step_pointer - 1 ) = _T('\0');\r
8063         }\r
8064         else {\r
8065                 e= stcpy_part_r( out_StepPath, StepPathSize, step_pointer, NULL,\r
8066                         abs_separator_pointer + 1, NULL ); IF(e)goto fin;\r
8067         }\r
8068 \r
8069         e=0;\r
8070 fin:\r
8071         return  e;\r
8072 \r
8073 err:  e = E_OTHERS;  goto fin;\r
8074 }\r
8075 \r
8076 \r
8077  \r
8078 /***********************************************************************\r
8079   <<< [StrT_getBaseName_part] >>> \r
8080 ************************************************************************/\r
8081 errnum_t  StrT_getBaseName_part( TCHAR* Str, size_t StrSize, TCHAR* StrStart,\r
8082         TCHAR** out_StrLast, const TCHAR* SrcPath )\r
8083 {\r
8084         const TCHAR*  p1;\r
8085         const TCHAR*  p2;\r
8086         const TCHAR*  p3;\r
8087         const TCHAR*  ps;\r
8088 \r
8089         p1 = StrT_refFName( SrcPath );\r
8090 \r
8091 \r
8092         //=== # \82ª\96³\82¢\82Æ\82«\81A\8dÅ\8cã\82Ì\83s\83\8a\83I\83h\82Ì\91O\82Ü\82Å\82ª\81ABaseName\r
8093         ps = _tcschr( p1, _T('#') );\r
8094         if ( ps == NULL ) {\r
8095                 p2 = _tcsrchr( p1, _T('.') );\r
8096                 if ( p2 == NULL )  p2 = _tcsrchr( p1, _T('\0') );\r
8097         }\r
8098 \r
8099         //=== # \82ª\82 \82é\82Æ\82«\81A# \82æ\82è\91O\82Å\81A\8dÅ\8cã\82Ì\83s\83\8a\83I\83h\82Ì\91O\82Ü\82Å\82ª\81ABaseName\r
8100         else {\r
8101                 p2 = ps;\r
8102 \r
8103                 p3 = p1;\r
8104                 for (;;) {\r
8105                         p3 = _tcschr( p3, _T('.') );\r
8106                         if ( p3 == NULL || p3 > ps )  break;\r
8107                         p2 = p3;\r
8108                         p3 ++;\r
8109                 }\r
8110         }\r
8111 \r
8112         return  stcpy_part_r( Str, StrSize, StrStart, out_StrLast, p1, p2 );\r
8113 }\r
8114 \r
8115  \r
8116 /***********************************************************************\r
8117   <<< [StrT_addLastOfFileName] >>> \r
8118 ************************************************************************/\r
8119 errnum_t  StrT_addLastOfFileName( TCHAR* out_Path, size_t PathSize,\r
8120                              const TCHAR* BasePath, const TCHAR* AddName )\r
8121 {\r
8122         TCHAR           c;\r
8123         size_t          copy_size;\r
8124         size_t          free_size;\r
8125         char*           out_pos;\r
8126         const TCHAR*    last_pos_in_base = StrT_chr( BasePath, _T('\0') );\r
8127         const TCHAR*    term_pos_in_base;\r
8128         const TCHAR*     add_pos_in_base;\r
8129         const TCHAR*  period_pos_in_base = _tcsrchr( BasePath, _T('.') );  // > term_pos_in_base\r
8130         const TCHAR*    last_pos_in_add  = StrT_chr( AddName, _T('\0') );\r
8131         const TCHAR*    term_pos_in_add;\r
8132         const TCHAR*  period_pos_in_add  = _tcsrchr( AddName,  _T('.') );  // > term_pos_in_add\r
8133 \r
8134 \r
8135         DISCARD_BYTES( out_Path, PathSize );\r
8136 \r
8137 \r
8138         //=== term_pos_in_base\r
8139         for ( term_pos_in_base = last_pos_in_base;  term_pos_in_base >= BasePath;  term_pos_in_base -- ) {\r
8140                 c = *term_pos_in_base;\r
8141                 if ( c == _T('/') || c == _T('\\') )  break;\r
8142         }\r
8143 \r
8144 \r
8145         //=== term_pos_in_add\r
8146         for ( term_pos_in_add = last_pos_in_add;  term_pos_in_add >= AddName;  term_pos_in_add -- ) {\r
8147                 c = *term_pos_in_add;\r
8148                 if ( c == _T('/') || c == _T('\\') )  break;\r
8149         }\r
8150 \r
8151 \r
8152         //=== add_pos_in_base\r
8153         if ( term_pos_in_base < period_pos_in_base ) {\r
8154                 add_pos_in_base = period_pos_in_base;\r
8155         }\r
8156         else {\r
8157                 if ( term_pos_in_base < BasePath )\r
8158                         add_pos_in_base = StrT_chr( BasePath, _T('\0') );\r
8159                 else\r
8160                         add_pos_in_base = StrT_chr( term_pos_in_base, _T('\0') );\r
8161         }\r
8162 \r
8163 \r
8164         //=== setup output parameters\r
8165         out_pos   = (char*) out_Path;\r
8166         free_size = PathSize;\r
8167 \r
8168 \r
8169         //=== copy BasePath .. add_pos_in_base\r
8170         copy_size = (char*)add_pos_in_base - (char*)BasePath;\r
8171         if ( copy_size > free_size ) goto err_fa;\r
8172         memcpy( out_pos,  BasePath,  copy_size );\r
8173         out_pos   += copy_size;\r
8174         free_size -= copy_size;\r
8175 \r
8176 \r
8177         //=== copy AddName .. last_pos_in_add\r
8178         copy_size = (char*)last_pos_in_add - (char*)AddName;\r
8179         if ( copy_size > free_size ) goto err_fa;\r
8180         memcpy( out_pos,  AddName,  copy_size );\r
8181         out_pos   += copy_size;\r
8182         free_size -= copy_size;\r
8183 \r
8184 \r
8185         //=== add name and not change extension\r
8186         if ( period_pos_in_add == NULL ) {\r
8187 \r
8188                 //=== copy period_pos_in_base .. last_pos_in_base\r
8189                 if ( period_pos_in_base > term_pos_in_base ) {\r
8190                         copy_size = (char*)last_pos_in_base - (char*)period_pos_in_base + sizeof(TCHAR);\r
8191                         if ( copy_size > free_size ) goto err_fa;\r
8192                         memcpy( out_pos,  period_pos_in_base,  copy_size );\r
8193                 }\r
8194                 else {\r
8195                         *(TCHAR*)out_pos = _T('\0');\r
8196                 }\r
8197         }\r
8198 \r
8199 \r
8200         //=== add name and change extension\r
8201         else {\r
8202 \r
8203                 if ( *(period_pos_in_add + 1) == _T('\0') )\r
8204                         *( (TCHAR*)out_pos - 1 ) = _T('\0');\r
8205                 else\r
8206                         *(TCHAR*)out_pos = _T('\0');\r
8207         }\r
8208 \r
8209         return  0;\r
8210 \r
8211 err_fa:\r
8212         return  E_FEW_ARRAY;\r
8213 }\r
8214 \r
8215 \r
8216  \r
8217 /***********************************************************************\r
8218   <<< [StrT_encodeToValidPath] >>> \r
8219 ************************************************************************/\r
8220 errnum_t  StrT_encodeToValidPath( TCHAR* out_Path,  size_t in_OutPathSize,  const TCHAR* in_Path,  bool  in_IsName )\r
8221 {\r
8222         errnum_t  e;\r
8223 \r
8224         int  i_in;   /* index of "in_Path" */\r
8225         int  i_out = 0;  /* index of "out_Path" */\r
8226         int  i_out_over = (int)( in_OutPathSize / sizeof(TCHAR) );\r
8227         bool is_colon = in_IsName;\r
8228 \r
8229         ASSERT_R( in_Path != out_Path,  e=E_OTHERS; goto fin );\r
8230 \r
8231         for ( i_in = 0;  ;  i_in += 1 ) {\r
8232                 bool  is_percent;\r
8233                 int   chara = in_Path[ i_in ];  /* a character */\r
8234 \r
8235                 if ( chara == _T('\0') )\r
8236                         { break; }\r
8237 \r
8238 \r
8239                 /* Set "is_percent" */\r
8240                 switch ( chara ) {\r
8241                         case _T(','):  case _T(';'):  case _T('*'):  case _T('?'):  case _T('"'):\r
8242                         case _T('<'):  case _T('>'):  case _T('|'):  case _T('%'):\r
8243                                 is_percent = true;\r
8244                                 break;\r
8245                         case _T(':'):\r
8246                                 is_percent = is_colon;\r
8247                                 is_colon = true;\r
8248                                 break;\r
8249                         case _T('\\'):  case _T('/'):\r
8250                                 is_percent = in_IsName;\r
8251                                 is_colon = true;\r
8252                                 break;\r
8253                         default:\r
8254                                 is_percent = false;\r
8255                                 break;\r
8256                 }\r
8257 \r
8258 \r
8259                 /* Set "out_Path[ i_out ]" */\r
8260                 if ( is_percent ) {\r
8261                         int  high = chara / 0x10;\r
8262                         int  low  = chara & 0xF;\r
8263 \r
8264                         if ( high <= 9 ) {\r
8265                                 high += _T('0');\r
8266                         } else {\r
8267                                 high = ( high - 0xA ) + _T('a');\r
8268                         }\r
8269 \r
8270                         if ( low <= 9 ) {\r
8271                                 low += _T('0');\r
8272                         } else {\r
8273                                 low = ( low - 0xA ) + _T('a');\r
8274                         }\r
8275 \r
8276                         ASSERT_R( i_out + 3 < i_out_over,  e=E_FEW_ARRAY; goto fin );\r
8277 \r
8278                         out_Path[ i_out + 0 ] = _T('%');\r
8279                         out_Path[ i_out + 1 ] = (TCHAR) high;\r
8280                         out_Path[ i_out + 2 ] = (TCHAR) low;\r
8281                         i_out += 3;\r
8282                 }\r
8283                 else {\r
8284                         ASSERT_R( i_out + 1 < i_out_over,  e=E_FEW_ARRAY; goto fin );\r
8285 \r
8286                         out_Path[ i_out ] = (TCHAR) chara;\r
8287                         i_out += 1;\r
8288                 }\r
8289         }\r
8290 \r
8291         e=0;\r
8292 fin:\r
8293         out_Path[ i_out ] = _T('\0');\r
8294 \r
8295         return  e;\r
8296 }\r
8297 \r
8298 \r
8299  \r
8300 /***********************************************************************\r
8301   <<< [Strs_init] >>> \r
8302 ************************************************************************/\r
8303 enum { Strs_FirstSize = 0x0F00 };\r
8304 \r
8305 errnum_t  Strs_init( Strs* self )\r
8306 {\r
8307         byte_t*  p;\r
8308 \r
8309         self->MemoryAddress = NULL;\r
8310 \r
8311         p = (byte_t*) malloc( Strs_FirstSize );\r
8312         IF( p == NULL )  return  E_FEW_MEMORY;\r
8313 \r
8314         self->MemoryAddress = p;\r
8315         self->MemoryOver    = p + Strs_FirstSize;\r
8316         self->NextElem      = p + sizeof(TCHAR*);\r
8317         self->PointerToNextStrInPrevElem = (TCHAR**) p;\r
8318         self->Prev_PointerToNextStrInPrevElem = NULL;\r
8319         *(TCHAR**) p = NULL;\r
8320 \r
8321         self->FirstOfStrs = self;\r
8322         self->NextStrs = NULL;\r
8323 \r
8324         return  0;\r
8325 }\r
8326 \r
8327 \r
8328  \r
8329 /***********************************************************************\r
8330   <<< [Strs_finish] >>> \r
8331 ************************************************************************/\r
8332 errnum_t  Strs_finish( Strs* self, errnum_t e )\r
8333 {\r
8334         Strs*  mp;\r
8335         Strs*  next_mp;\r
8336 \r
8337         if ( self->MemoryAddress == NULL )  return 0;\r
8338 \r
8339         mp = self->FirstOfStrs;\r
8340         for (;;) {\r
8341                 free( mp->MemoryAddress );\r
8342                 if ( mp == self )  break;\r
8343 \r
8344                 next_mp = mp->NextStrs;\r
8345                 free( mp );\r
8346                 mp = next_mp;\r
8347         }\r
8348         self->MemoryAddress = NULL;\r
8349 \r
8350         return  e;\r
8351 }\r
8352 \r
8353 \r
8354  \r
8355 /***********************************************************************\r
8356   <<< [Strs_toEmpty] >>> \r
8357 ************************************************************************/\r
8358 errnum_t  Strs_toEmpty( Strs* self )\r
8359 {\r
8360         Strs_finish( self, 0 );\r
8361         return  Strs_init( self );\r
8362 }\r
8363 \r
8364 \r
8365  \r
8366 /***********************************************************************\r
8367   <<< [Strs_add] >>> \r
8368 ************************************************************************/\r
8369 errnum_t  Strs_add( Strs* self, const TCHAR* Str, const TCHAR** out_AllocStr )\r
8370 {\r
8371         return  Strs_addBinary( self, Str, StrT_chr( Str, _T('\0') ) + 1, out_AllocStr );\r
8372 }\r
8373 \r
8374 \r
8375 errnum_t  Strs_addBinary( Strs* self, const TCHAR* Str, const TCHAR* StrOver, const TCHAR** out_AllocStr )\r
8376 {\r
8377         errnum_t  e;\r
8378         size_t  str_size;\r
8379         size_t  elem_size;\r
8380 \r
8381         str_size  = ( (byte_t*) StrOver - (byte_t*) Str );\r
8382         elem_size = ( sizeof(TCHAR*) + str_size + ( sizeof(void*) - 1 ) ) & ~(sizeof(void*) - 1);\r
8383 \r
8384         if ( self->NextElem + elem_size > self->MemoryOver )\r
8385                 { e= Strs_expandSize( self, str_size ); IF(e)goto fin; }\r
8386 \r
8387 \r
8388         // [ NULL     | ... ]\r
8389         // [ FirstStr | NULL    | TCHAR[] | ... ]\r
8390         // [ FirstStr | NextStr | TCHAR[] | NULL    | TCHAR[] | ... ]\r
8391         // [ FirstStr | NextStr | TCHAR[] | NextStr | TCHAR[] ], [ NULL | TCHAR[] | ... ]\r
8392 \r
8393         if ( out_AllocStr != NULL )  *out_AllocStr = (TCHAR*)( self->NextElem + sizeof(TCHAR*) );\r
8394 \r
8395         //=== fill elem\r
8396         *(TCHAR**) self->NextElem = NULL;\r
8397         memcpy( self->NextElem + sizeof(TCHAR*),  Str,  str_size );\r
8398 \r
8399         //=== link to elem from previous elem\r
8400         *self->PointerToNextStrInPrevElem = (TCHAR*)( self->NextElem + sizeof(TCHAR*) );\r
8401 \r
8402         //=== update self\r
8403         self->Prev_PointerToNextStrInPrevElem = self->PointerToNextStrInPrevElem;\r
8404         self->PointerToNextStrInPrevElem = (TCHAR**) self->NextElem;\r
8405         self->NextElem = self->NextElem + elem_size;\r
8406 \r
8407         e=0;\r
8408 fin:\r
8409         return  e;\r
8410 }\r
8411 \r
8412 \r
8413  \r
8414 /***********************************************************************\r
8415   <<< [Strs_freeLast] >>> \r
8416 ************************************************************************/\r
8417 errnum_t  Strs_freeLast( Strs* self, TCHAR* AllocStr )\r
8418 {\r
8419         errnum_t  e;\r
8420         TCHAR*  str;\r
8421         TCHAR*  last_str;\r
8422         TCHAR*  prev_of_last_str;\r
8423         Strs*   mp;\r
8424         Strs*   prev_of_last_mp;\r
8425 \r
8426         if ( self->Prev_PointerToNextStrInPrevElem == NULL ) {\r
8427                 prev_of_last_str = NULL;\r
8428                 last_str = NULL;\r
8429                 for ( Strs_forEach( self, &str ) ) {\r
8430                         prev_of_last_str = last_str;\r
8431                         last_str = str;\r
8432                 }\r
8433         }\r
8434         else {\r
8435                 prev_of_last_str = (TCHAR*)( self->Prev_PointerToNextStrInPrevElem + 1 );\r
8436                 last_str = (TCHAR*)( self->PointerToNextStrInPrevElem + 1 );\r
8437         }\r
8438 \r
8439         // [ NULL     | ... ]\r
8440         IF( last_str != AllocStr ) {goto err;}\r
8441 \r
8442         // [ FirstStr | NULL    | TCHAR[] | ... ]\r
8443         if ( prev_of_last_str == NULL ) {\r
8444                 self->NextElem = self->MemoryAddress + sizeof(TCHAR*);\r
8445                 self->PointerToNextStrInPrevElem = (TCHAR**) self->MemoryAddress;\r
8446         }\r
8447 \r
8448         // [ FirstStr | NextStr | TCHAR[] | NULL    | TCHAR[] | ... ]\r
8449         else if ( (byte_t*) prev_of_last_str >= self->MemoryAddress  &&\r
8450                   (byte_t*) prev_of_last_str <  self->MemoryOver ) {\r
8451                 self->NextElem = (byte_t*)last_str - sizeof(TCHAR*);\r
8452                 self->PointerToNextStrInPrevElem = (TCHAR**)( (byte_t*)prev_of_last_str - sizeof(TCHAR*) );\r
8453         }\r
8454 \r
8455         // [ FirstStr | NextStr | TCHAR[] | NextStr | TCHAR[] ], [ NULL | TCHAR[] | ... ]\r
8456         else {\r
8457                 prev_of_last_mp = NULL;\r
8458                 for ( mp = self->FirstOfStrs;  mp->NextStrs != self;  mp = mp->NextStrs ) {\r
8459                         prev_of_last_mp = mp;\r
8460                 }\r
8461 \r
8462                 free( self->MemoryAddress );\r
8463 \r
8464                 *self = *mp;\r
8465 \r
8466                 if ( prev_of_last_mp == NULL ) {\r
8467                         self->FirstOfStrs = self;\r
8468                         self->NextStrs = NULL;\r
8469                 }\r
8470                 else {\r
8471                         prev_of_last_mp->NextStrs = self;\r
8472                 }\r
8473 \r
8474                 free( mp );\r
8475         }\r
8476         *self->PointerToNextStrInPrevElem = NULL;\r
8477         self->Prev_PointerToNextStrInPrevElem = NULL;\r
8478 \r
8479         e=0;\r
8480 fin:\r
8481         return  e;\r
8482 \r
8483 err:  e = E_OTHERS;  goto fin;\r
8484 }\r
8485 \r
8486 \r
8487  \r
8488 /***********************************************************************\r
8489   <<< [Strs_expandSize] >>> \r
8490 ************************************************************************/\r
8491 errnum_t  Strs_expandSize( Strs* self, size_t FreeSize )\r
8492 {\r
8493         Strs*   mp;\r
8494         Strs*   mp2;\r
8495         size_t  elem_size = ( sizeof(TCHAR*) + FreeSize + sizeof(void*) - 1 ) & ~(sizeof(void*) - 1);\r
8496         size_t  memory_size;\r
8497         byte_t* new_memory;\r
8498 \r
8499         // [ NULL     | ... ]\r
8500         // [ FirstStr | NULL    | TCHAR[] | ... ]\r
8501         // [ FirstStr | NextStr | TCHAR[] | NULL    | TCHAR[] | ... ]\r
8502         // [ FirstStr | NextStr | TCHAR[] | NextStr | TCHAR[] ], [ NULL | TCHAR[] | ... ]\r
8503 \r
8504         while ( self->NextElem + elem_size > self->MemoryOver ) {\r
8505 \r
8506                 //=== alloc\r
8507                 mp = (Strs*) malloc( sizeof(Strs) ); IF(mp==NULL) goto err_fm;\r
8508                 memory_size = ( self->MemoryOver - self->MemoryAddress ) * 2;\r
8509                 new_memory = (byte_t*) malloc( memory_size );\r
8510                 IF( new_memory == NULL )  { free( mp );  goto err_fm; }\r
8511 \r
8512                 //=== move old memory\r
8513                 if ( self->FirstOfStrs == self ) {\r
8514                         self->FirstOfStrs = mp;\r
8515                 }\r
8516                 else {\r
8517                         for ( mp2 = self->FirstOfStrs;  mp2->NextStrs != self;  mp2 = mp2->NextStrs );\r
8518                         mp2->NextStrs = mp;\r
8519                 }\r
8520                 *mp = *self;\r
8521                 mp->NextStrs = self;\r
8522 \r
8523                 //=== setup new memory\r
8524                 self->MemoryAddress = new_memory;\r
8525                 self->MemoryOver    = new_memory + memory_size;\r
8526                 self->NextElem      = new_memory;\r
8527                 // self->PointerToNextStrInPrevElem is same value\r
8528                 // self->FirstOfStrs is same value\r
8529                 // self->NextStrs is always NULL\r
8530         }\r
8531         return  0;\r
8532 \r
8533 err_fm:  return  E_FEW_ARRAY;\r
8534 }\r
8535 \r
8536 \r
8537 /***********************************************************************\r
8538   <<< [Strs_commit] >>>\r
8539 ************************************************************************/\r
8540 errnum_t  Strs_commit( Strs* self, TCHAR* StrOver )\r
8541 {\r
8542         size_t  elem_size;\r
8543 \r
8544         if ( StrOver == NULL )\r
8545                 { StrOver = StrT_chr( (TCHAR*)( self->NextElem + sizeof(TCHAR*) ), _T('\0') ) + 1; }\r
8546         elem_size = ( ( (byte_t*)StrOver - self->NextElem ) + sizeof(void*) - 1 ) & ~(sizeof(void*) - 1);\r
8547 \r
8548         //=== fill elem\r
8549         *(TCHAR**) self->NextElem = NULL;\r
8550 \r
8551         //=== link to elem from previous elem\r
8552         *self->PointerToNextStrInPrevElem = (TCHAR*)( self->NextElem + sizeof(TCHAR*) );\r
8553 \r
8554         //=== update self\r
8555         self->PointerToNextStrInPrevElem = (TCHAR**) self->NextElem;\r
8556         self->NextElem = self->NextElem + elem_size;\r
8557 \r
8558         return  0;\r
8559 }\r
8560 \r
8561 \r
8562  \r
8563 /***********************************************************************\r
8564   <<< [Strs_allocateArray] >>> \r
8565 ************************************************************************/\r
8566 errnum_t  Strs_allocateArray( Strs* self,  TCHAR*** out_PointerArray,  int* out_Count )\r
8567 {\r
8568         errnum_t  e;\r
8569         TCHAR*    p;\r
8570         TCHAR**   pp;\r
8571         int       count;\r
8572 \r
8573         count = 0;\r
8574         for ( Strs_forEach( self, &p ) ) {\r
8575                 count += 1;\r
8576         }\r
8577 \r
8578         e= HeapMemory_allocateArray( &pp, count ); IF(e){goto fin;}\r
8579 \r
8580         count = 0;\r
8581         for ( Strs_forEach( self, &p ) ) {\r
8582                 pp[ count ] = p;\r
8583                 count += 1;\r
8584         }\r
8585 \r
8586         *out_PointerArray = pp;\r
8587         *out_Count = count;\r
8588 \r
8589         e=0;\r
8590 fin:\r
8591         return  e;\r
8592 }\r
8593 \r
8594 \r
8595  \r
8596 /***********************************************************************\r
8597   <<< [StrArr] >>> \r
8598 ************************************************************************/\r
8599 \r
8600 /*[StrArr_init]*/\r
8601 errnum_t  StrArr_init( StrArr* self )\r
8602 {\r
8603         errnum_t  e;\r
8604 \r
8605         Set2_initConst( &self->Array );\r
8606         Strs_initConst( &self->Chars );\r
8607 \r
8608         e= Set2_init( &self->Array, 0x100 ); IF(e)goto cancel;\r
8609         e= Strs_init( &self->Chars ); IF(e)goto cancel;\r
8610         return  0;\r
8611 \r
8612 cancel:  StrArr_finish( self, e );  return  e;\r
8613 }\r
8614 \r
8615 \r
8616 /*[StrArr_finish]*/\r
8617 errnum_t  StrArr_finish( StrArr* self, errnum_t e )\r
8618 {\r
8619         if ( ! Set2_isInited( &self->Array ) )  return  e;\r
8620 \r
8621         e= Set2_finish( &self->Array, e );\r
8622         e= Strs_finish( &self->Chars, e );\r
8623         return  e;\r
8624 }\r
8625 \r
8626 \r
8627 /*[StrArr_add]*/\r
8628 errnum_t  StrArr_add( StrArr* self, const TCHAR* Str, int* out_I )\r
8629 {\r
8630         errnum_t  e;\r
8631 \r
8632         e= StrArr_expandCount( self, _tcslen( Str ) ); IF(e)goto fin;\r
8633         _tcscpy_s( StrArr_getFreeAddr( self ), StrArr_getFreeCount( self ), Str );\r
8634         e= StrArr_commit( self ); IF(e)goto fin;\r
8635         if ( out_I != NULL )  *out_I = Set2_getCount( &self->Array, TCHAR* ) - 1;\r
8636 \r
8637         e=0;\r
8638 fin:\r
8639         return  e;\r
8640 }\r
8641 \r
8642 \r
8643 /*[StrArr_commit]*/\r
8644 errnum_t  StrArr_commit( StrArr* self )\r
8645 {\r
8646         errnum_t  e;\r
8647         TCHAR*   p;\r
8648         TCHAR**  pp  = NULL;\r
8649         Set2*    arr = &self->Array;\r
8650         Strs*    ss  = &self->Chars;\r
8651 \r
8652         p = Strs_getFreeAddr( ss );\r
8653         e= Set2_alloc( arr, &pp, TCHAR* ); IF(e)goto fin;\r
8654         e= Strs_commit( ss, NULL ); IF(e)goto fin;\r
8655         *pp = p;\r
8656 \r
8657         e=0;\r
8658 fin:\r
8659         if ( e &&  pp != NULL )  e= Set2_freeLast( arr, pp, TCHAR*, e );\r
8660         return  e;\r
8661 }\r
8662 \r
8663 \r
8664 /*[StrArr_fillTo]*/\r
8665 errnum_t  StrArr_fillTo( StrArr* self, int n, const TCHAR* Str )\r
8666 {\r
8667         errnum_t  e;\r
8668         const TCHAR*   p;\r
8669         const TCHAR**  pp;\r
8670         const TCHAR**  pp_over;\r
8671 \r
8672         n -= Set2_getCount( &self->Array, TCHAR* );\r
8673         if ( n <= 0 ) return 0;\r
8674 \r
8675         if ( Str == NULL ) {\r
8676                 p = NULL;\r
8677         }\r
8678         else {\r
8679                 e= Strs_add( &self->Chars, Str, &p ); IF(e)goto fin;\r
8680         }\r
8681 \r
8682         e= Set2_allocMulti( &self->Array, &pp, TCHAR*, n ); IF(e)goto fin;\r
8683         pp_over = pp + n;\r
8684         for ( ;  pp < pp_over;  pp++ )\r
8685                 *pp = p;\r
8686 \r
8687         e=0;\r
8688 fin:\r
8689         return  e;\r
8690 }\r
8691 \r
8692 \r
8693 /*[StrArr_toEmpty]*/\r
8694 errnum_t  StrArr_toEmpty( StrArr* self )\r
8695 {\r
8696         errnum_t  e, ee;\r
8697 \r
8698         e=0;\r
8699         ee= Set2_toEmpty( &self->Array ); IF(ee&&!e)e=ee;\r
8700         ee= Strs_toEmpty( &self->Chars ); IF(ee&&!e)e=ee;\r
8701         return  e;\r
8702 }\r
8703 \r
8704 \r
8705  \r
8706 /***********************************************************************\r
8707   <<< [StrArr_parseCSV] >>> \r
8708 ************************************************************************/\r
8709 errnum_t  StrArr_parseCSV( StrArr* self, const TCHAR* CSVLine )\r
8710 {\r
8711         errnum_t      e;\r
8712         const TCHAR*  p = CSVLine;\r
8713 \r
8714         e= StrArr_toEmpty( self ); IF(e)goto fin;\r
8715 \r
8716         do {\r
8717                 e= StrT_meltCSV( StrArr_getFreeAddr( self ), StrArr_getFreeSize( self ), &p );\r
8718                 if ( e == E_FEW_ARRAY ) {\r
8719                         e= StrArr_expandSize( self, StrArr_getFreeSize( self ) * 2 ); IF(e)goto fin;\r
8720                         continue;\r
8721                 }\r
8722                 IF(e)goto fin;\r
8723 \r
8724                 e = StrArr_commit( self ); IF(e)goto fin;\r
8725         } while ( p != NULL );\r
8726 \r
8727         e=0;\r
8728 fin:\r
8729         return  e;\r
8730 }\r
8731 \r
8732 \r
8733  \r
8734 /*-------------------------------------------------------------------------*/\r
8735 /* <<<< ### (StrFile) Read Class implement >>>> */ \r
8736 /*-------------------------------------------------------------------------*/\r
8737 \r
8738 errnum_t  StrFile_init_sub( StrFile* self, void* Buffer, size_t BufferSize, int Flags );\r
8739 \r
8740 /*[StrFile_init_fromStr]*/\r
8741 errnum_t  StrFile_init_fromStr( StrFile* self, TCHAR* LinkStr )\r
8742 {\r
8743         self->IsBufferInHeap = false;\r
8744         #if _UNICODE\r
8745                 StrFile_init_sub( self, LinkStr,\r
8746                         (char*)StrT_chr( LinkStr, _T('\0') ) - (char*)LinkStr,  STR_FILE_WCHAR );\r
8747         #else\r
8748                 StrFile_init_sub( self, LinkStr,\r
8749                         (char*)StrT_chr( LinkStr, _T('\0') ) - (char*)LinkStr,  0 );\r
8750         #endif\r
8751 \r
8752         return  0;\r
8753 }\r
8754 \r
8755 \r
8756 /*[StrFile_initConst]*/\r
8757 void  StrFile_initConst( StrFile* self )\r
8758 {\r
8759         self->Buffer = NULL;\r
8760 }\r
8761 \r
8762 \r
8763 /*[StrFile_init_withBuf]*/\r
8764 errnum_t  StrFile_init_withBuf( StrFile* self, void* LinkBuffer, size_t LinkBufferSize, int Flags )\r
8765 {\r
8766         self->IsBufferInHeap = false;\r
8767         StrFile_init_sub( self, LinkBuffer, LinkBufferSize, Flags );\r
8768         return  0;\r
8769 }\r
8770 \r
8771 \r
8772 /*[StrFile_init_sub]*/\r
8773 errnum_t  StrFile_init_sub( StrFile* self, void* Buffer, size_t BufferSize, int Flags )\r
8774 {\r
8775         unsigned char*  top = (unsigned char*) Buffer;\r
8776 \r
8777         if ( Flags & STR_FILE_WCHAR ) {\r
8778                 self->CharSize = 2;\r
8779                 self->Pointer = top;\r
8780         }\r
8781         else {\r
8782                 // UTF-16 BOM= { FF, FE },  UTF-8 BOM = { EF, BB, BF }\r
8783                 if ( BufferSize >= 2  &&  top[0] == 0xFF  &&  top[1] == 0xFE ) {\r
8784                         self->CharSize = 2;\r
8785                         self->Pointer = top + 2;\r
8786                         if ( BufferSize % 2 == 1 )  BufferSize --;\r
8787                 }\r
8788                 else if ( BufferSize >= 3  &&  top[0] == 0xEF  &&  top[1] == 0xBB  &&  top[2] == 0xBF ) {\r
8789                         self->CharSize = 1;\r
8790                         self->Pointer = top + 3;\r
8791                 }\r
8792                 else {\r
8793                         self->CharSize = 1;\r
8794                         self->Pointer = top;\r
8795                 }\r
8796         }\r
8797 \r
8798         self->Buffer = Buffer;\r
8799         self->BufferSize = BufferSize;\r
8800         // self->IsBufferInHeap // not init in this function\r
8801 \r
8802         return  0;\r
8803 }\r
8804 \r
8805 \r
8806 /*[StrFile_init_fromSizedStructInStream]*/\r
8807 errnum_t  StrFile_init_fromSizedStructInStream( StrFile* self, HANDLE* Stream )\r
8808 {\r
8809         errnum_t  e;\r
8810 \r
8811         self->IsBufferInHeap = false;\r
8812 \r
8813         e= FileT_readSizedStruct_WinAPI( Stream, &self->Buffer ); IF(e)goto rollback;\r
8814         self->IsBufferInHeap = true;\r
8815         self->OffsetToHeapBlockFirst = - (int) sizeof(size_t);\r
8816         e= StrFile_init_sub( self, (size_t*)self->Buffer + 1,\r
8817                  *(size_t*)self->Buffer - sizeof(size_t), STR_FILE_READ ); IF(e)goto rollback;\r
8818         return  0;\r
8819 \r
8820 rollback:  StrFile_finish( self, e );  return  e;\r
8821 }\r
8822 \r
8823 \r
8824 /*[StrFile_finish]*/\r
8825 errnum_t  StrFile_finish( StrFile* self, errnum_t e )\r
8826 {\r
8827         if ( self->Buffer == NULL )  return  e;\r
8828         if ( self->IsBufferInHeap ) {\r
8829                 free( (char*) self->Buffer + self->OffsetToHeapBlockFirst );\r
8830                 self->IsBufferInHeap = false;\r
8831         }\r
8832         self->Buffer = NULL;\r
8833         return  e;\r
8834 }\r
8835 \r
8836 \r
8837 /*[StrFile_readLine]*/\r
8838 errnum_t  StrFile_readLine( StrFile* self, TCHAR* out_Line, size_t LineSize )\r
8839 {\r
8840         errnum_t  e;\r
8841         TCHAR*  last_of_line;\r
8842 \r
8843         if ( self->CharSize == 1 ) {\r
8844                 char*  ptr   = (char*) self->Pointer;\r
8845                 char*  first = ptr;\r
8846                 char*  over  = (char*) self->Buffer + self->BufferSize;\r
8847                 size_t size;\r
8848 \r
8849                 if ( ptr >= over ) goto err_nn;\r
8850 \r
8851                 for (;;) {\r
8852                         if ( ptr >= over )  { self->Pointer = (void*)0xFFFFFFFF;  break; }\r
8853                         if ( *ptr == '\n' )  { ptr++;  self->Pointer = ptr;  break; }\r
8854                         ptr ++;\r
8855                 }\r
8856                 size = ptr - first;\r
8857 \r
8858                 #if _UNICODE\r
8859                         if ( ptr < over ) {\r
8860                                 char  ch = *ptr;\r
8861 \r
8862                                 *ptr = '\0';\r
8863                                 e= stprintf_r( out_Line, LineSize, _T("%S"), first );\r
8864                                 *ptr = ch;\r
8865                                 IF(e)goto fin;\r
8866                         }\r
8867                         else {  // if cannot access *ptr\r
8868                                 char*  line;\r
8869 \r
8870                                 line = malloc( size + sizeof(char) );\r
8871                                 line[ size ] = '\0';\r
8872                                 memcpy( line, first, size );\r
8873 \r
8874                                 e= stprintf_r( out_Line, LineSize, _T("%S"), line );\r
8875                                 free( line );\r
8876                                 IF(e)goto fin;\r
8877                         }\r
8878                         last_of_line = StrT_chr( out_Line, _T('\0') );\r
8879                 #else\r
8880                         if ( size > LineSize - sizeof(char) )  goto err_fa;\r
8881 \r
8882                         last_of_line = out_Line + size;\r
8883                         *last_of_line = '\0';\r
8884                         memcpy( out_Line, first, size );\r
8885                 #endif\r
8886         }\r
8887         else {\r
8888                 wchar_t*  ptr   = (wchar_t*) self->Pointer;\r
8889                 wchar_t*  first = ptr;\r
8890                 wchar_t*  over  = (wchar_t*)( (char*) self->Buffer + self->BufferSize );\r
8891                 size_t    size;\r
8892 \r
8893                 ASSERT_D( self->CharSize == 2, goto err );\r
8894 \r
8895                 if ( ptr >= over ) goto err_nn;\r
8896 \r
8897                 for (;;) {\r
8898                         if ( ptr >= over )  { self->Pointer = (void*)0xFFFFFFFF;  break; }\r
8899                         if ( *ptr == L'\n' )  { ptr++;  self->Pointer = ptr;  break; }\r
8900                         ptr ++;\r
8901                 }\r
8902                 size = (char*) ptr - (char*) first;\r
8903 \r
8904                 #if _UNICODE\r
8905                         IF( size > LineSize - sizeof(TCHAR) ) goto err_fa;\r
8906 \r
8907                         last_of_line = (TCHAR*)( (char*) out_Line + size );\r
8908                         *last_of_line = _T('\0');\r
8909                         memcpy( out_Line, first, size );\r
8910                 #else\r
8911                         if ( ptr < over ) {\r
8912                                 wchar_t  ch = *ptr;\r
8913 \r
8914                                 *ptr = L'\0';\r
8915                                 e= stprintf_r( out_Line, LineSize, _T("%S"), first );\r
8916                                 *ptr = ch;\r
8917                                 IF(e)goto fin;\r
8918                                 last_of_line = StrT_chr( out_Line, _T('\0') );\r
8919                         }\r
8920                         else {  // if cannot access *ptr\r
8921                                 wchar_t  last_str[2];\r
8922 \r
8923                                 ptr --;\r
8924 \r
8925                                 last_str[0] = *ptr;\r
8926                                 last_str[1] = L'\0';\r
8927 \r
8928                                 *ptr = L'\0';\r
8929                                 e= stprintf_r( out_Line, LineSize, "%S", first );\r
8930                                 *ptr = last_str[0];\r
8931                                 IF(e)goto fin;\r
8932 \r
8933                                 last_of_line = StrT_chr( out_Line, _T('\0') );\r
8934                                 LineSize -= (char*) last_of_line - (char*) out_Line;\r
8935                                 e= stprintf_r( last_of_line, LineSize, "%S", last_str ); IF(e)goto fin;\r
8936                                 last_of_line = StrT_chr( last_of_line, _T('\0') );\r
8937                         }\r
8938                 #endif\r
8939         }\r
8940 \r
8941         // change from CR+LF to LF (text mode)\r
8942         if ( last_of_line >= out_Line + 2 ) {\r
8943                 if ( *(last_of_line - 2) == _T('\r')  &&  *(last_of_line - 1) == _T('\n') ) {\r
8944                         *(last_of_line - 2) = _T('\n');  *(last_of_line - 1) = _T('\0');\r
8945                 }\r
8946         }\r
8947 \r
8948         e=0;\r
8949 fin:\r
8950         return  e;\r
8951 \r
8952 err_fa:  e = E_FEW_ARRAY;  goto fin;\r
8953 err_nn:  self->Pointer = (void*)0xFFFFFFFF;  e=0;  goto fin;  // not [e = E_NO_NEXT], because ferror()==0\r
8954 #if _DEBUG\r
8955 err:  e = E_OTHERS;  goto fin;\r
8956 #endif\r
8957 }\r
8958 \r
8959 \r
8960  \r
8961 /*-------------------------------------------------------------------------*/\r
8962 /* <<<< ### (StrFile) Write Class implement >>>> */ \r
8963 /*-------------------------------------------------------------------------*/\r
8964 \r
8965 errnum_t  StrFile_expandIfOver_sub( StrFile* self, size_t DataSize );\r
8966 \r
8967 \r
8968 //[StrFile_init_toHeap]\r
8969 errnum_t  StrFile_init_toHeap( StrFile* self, int Flags )\r
8970 {\r
8971         void*  mem;\r
8972         enum { start_size = 480 };\r
8973 \r
8974         mem = malloc( start_size );  IF ( mem == NULL )  return  E_FEW_MEMORY;\r
8975 \r
8976         self->Buffer = (char*) mem + sizeof(size_t);\r
8977         self->BufferSize = start_size - sizeof(size_t);\r
8978         self->IsBufferInHeap = true;\r
8979         self->IsTextMode = ( (Flags & STR_FILE_BINARY) == 0 );\r
8980         self->OffsetToHeapBlockFirst = - (int) sizeof(size_t);\r
8981         if ( Flags & STR_FILE_WCHAR ) {\r
8982                 wchar_t*  wp = (wchar_t*) self->Buffer;\r
8983 \r
8984                 wp[0] = 0xFEFF;\r
8985                 wp[1] = L'\0';\r
8986 \r
8987                 self->CharSize = 2;\r
8988                 self->Pointer = (char*) self->Buffer + sizeof(wchar_t);\r
8989         }\r
8990         else {\r
8991                 char*  ap = (char*) self->Buffer;\r
8992 \r
8993                 ap[0] = '\0';\r
8994 \r
8995                 self->CharSize = 1;\r
8996                 self->Pointer = (char*) self->Buffer;\r
8997         }\r
8998         return  0;\r
8999 }\r
9000 \r
9001 \r
9002 //[StrFile_write_s]\r
9003 errnum_t  StrFile_write_s( StrFile* self, const TCHAR* Text )\r
9004 {\r
9005         errnum_t        e;\r
9006         const char*     pos1;\r
9007         const char*     pos2;\r
9008         #if _UNICODE\r
9009                 char*         str = NULL;\r
9010                 size_t        str_size;\r
9011         #endif\r
9012 \r
9013         #if _UNICODE\r
9014                 str_size = (_tcslen( Text ) + 1) * sizeof(wchar_t); // max is for all 2byte charactors\r
9015                 str = malloc( str_size ); IF( str == NULL )goto err_fm;\r
9016                 sprintf_s( str, str_size, "%S", Text ); // conver to multi byte char\r
9017                 pos1 = str;\r
9018         #else\r
9019                 pos1 = Text;\r
9020         #endif\r
9021 \r
9022         if ( self->IsTextMode ) {\r
9023                 for (;;) {\r
9024                         pos2 = strchr( pos1, '\n' );\r
9025                         if ( pos2 == NULL )  break;\r
9026 \r
9027                         // write 1 line and change from \n to CR LF\r
9028                         e= StrFile_writeBinary( self,  pos1,  (char*) pos2 - (char*) pos1 + 2 * sizeof(char) );\r
9029                                 IF(e)goto fin;\r
9030                         ( (char*) self->Pointer )[-2] = '\r';\r
9031                         ( (char*) self->Pointer )[-1] = '\n';\r
9032 \r
9033                         pos1 = pos2 + 1;\r
9034                 }\r
9035         }\r
9036 \r
9037         // if "IsTextMode", write last line\r
9038         // if not "IsTextMode", write whole text\r
9039         pos2 = strchr( pos1, '\0' );\r
9040         e= StrFile_writeBinary( self,  pos1,  (char*) pos2 - (char*) pos1 + sizeof(char) );\r
9041                 IF(e)goto fin;\r
9042         self->Pointer = (char*) self->Pointer - sizeof(char);\r
9043 \r
9044 \r
9045         e=0;\r
9046 fin:\r
9047         #if _UNICODE\r
9048                 if ( str != NULL )  free( str );\r
9049         #endif\r
9050         return  e;\r
9051 \r
9052 #if _UNICODE\r
9053 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
9054 #endif\r
9055 }\r
9056 \r
9057 \r
9058 //[StrFile_write_w]\r
9059 errnum_t  StrFile_write_w( StrFile* self, const TCHAR* Text )\r
9060 {\r
9061         errnum_t        e;\r
9062         const wchar_t*  pos1;\r
9063         const wchar_t*  pos2;\r
9064         #if ! _UNICODE\r
9065                 wchar_t*      str = NULL;\r
9066                 size_t        str_size;\r
9067         #endif\r
9068 \r
9069         #if _UNICODE\r
9070                 pos1 = Text;\r
9071         #else\r
9072                 str_size = (_tcslen( Text ) + 1) * sizeof(wchar_t); // max is for all 1byte char to wchar_t\r
9073                 str = malloc( str_size ); IF( str == NULL )goto err_fm;\r
9074                 swprintf_s( str, str_size / sizeof(wchar_t), L"%S", Text ); // conver to wide byte char\r
9075                 pos1 = str;\r
9076         #endif\r
9077 \r
9078         if ( self->IsTextMode ) {\r
9079                 for (;;) {\r
9080                         pos2 = wcschr( pos1, L'\n' );\r
9081                         if ( pos2 == NULL )  break;\r
9082 \r
9083                         // write 1 line and change from \n to CR LF\r
9084                         e= StrFile_writeBinary( self,  pos1,  (char*) pos2 - (char*) pos1 + 2 * sizeof(wchar_t) );\r
9085                                 IF(e)goto fin;\r
9086                         ( (wchar_t*) self->Pointer )[-2] = L'\r';\r
9087                         ( (wchar_t*) self->Pointer )[-1] = L'\n';\r
9088 \r
9089                         pos1 = pos2 + 1;\r
9090                 }\r
9091         }\r
9092 \r
9093         // if "IsTextMode", write last line\r
9094         // if not "IsTextMode", write whole text\r
9095         pos2 = wcschr( pos1, L'\0' );\r
9096         e= StrFile_writeBinary( self,  pos1,  (char*) pos2 - (char*) pos1 + sizeof(wchar_t) );\r
9097                 IF(e)goto fin;\r
9098         self->Pointer = (char*) self->Pointer - sizeof(wchar_t);\r
9099 \r
9100         e=0;\r
9101 fin:\r
9102         #if ! _UNICODE\r
9103                 if ( str != NULL )  free( str );\r
9104         #endif\r
9105         return  e;\r
9106 \r
9107 #if ! _UNICODE\r
9108 err_fm:  e = E_FEW_MEMORY;  goto fin;\r
9109 #endif\r
9110 }\r
9111 \r
9112 \r
9113 //[StrFile_write]\r
9114 errnum_t  StrFile_write( StrFile* self, const TCHAR* Text )\r
9115 {\r
9116         if ( self->CharSize == 1 )  return  StrFile_write_s( self, Text );\r
9117         else                        return  StrFile_write_w( self, Text );\r
9118 }\r
9119 \r
9120 \r
9121 //[StrFile_expandIfOver]\r
9122 errnum_t  StrFile_expandIfOver( StrFile* self, size_t DataSize )\r
9123 {\r
9124         if ( (char*) self->Pointer + DataSize <= (char*) self->Buffer + self->BufferSize )  return  0;\r
9125         else  return  StrFile_expandIfOver_sub( self, DataSize );\r
9126 }\r
9127 \r
9128 \r
9129 //[StrFile_writeBinary]\r
9130 errnum_t  StrFile_writeBinary( StrFile* self, const void* Data, size_t DataSize )\r
9131 {\r
9132         errnum_t  e;\r
9133 \r
9134         e= StrFile_expandIfOver( self, DataSize ); if(e)return e;\r
9135         memcpy( self->Pointer, Data, DataSize );\r
9136         self->Pointer = (char*) self->Pointer + DataSize;\r
9137         return  0;\r
9138 }\r
9139 \r
9140 \r
9141 //[StrFile_expandIfOver_sub]\r
9142 errnum_t  StrFile_expandIfOver_sub( StrFile* self, size_t DataSize )\r
9143 {\r
9144         errnum_t  e;\r
9145         void*   mem;\r
9146         size_t  old_size = (char*) self->Pointer - (char*) self->Buffer;\r
9147         size_t  new_size = ( self->BufferSize + sizeof(size_t) ) * 2 + DataSize;\r
9148 \r
9149         IF( ! self->IsBufferInHeap ) {goto err;}\r
9150                 // Writing must expand self->Buffer from heap when self->Buffer is small\r
9151 \r
9152         mem = realloc( (char*) self->Buffer + self->OffsetToHeapBlockFirst,  new_size );\r
9153                 IF(mem == NULL) goto err_fa;\r
9154 \r
9155         self->Buffer = (char*) mem + sizeof(size_t);\r
9156         self->BufferSize = new_size - sizeof(size_t);\r
9157         self->OffsetToHeapBlockFirst = - (int) sizeof(size_t);\r
9158         self->Pointer = (char*) self->Buffer + old_size;\r
9159 \r
9160         e=0;\r
9161 fin:\r
9162         return  e;\r
9163 \r
9164 err_fa:  e = E_FEW_ARRAY;  goto fin;\r
9165 err:     e = E_OTHERS;  goto fin;\r
9166 }\r
9167 \r
9168 \r
9169 //[StrFile_peekWrittenStringW]\r
9170 errnum_t  StrFile_peekWrittenStringW( StrFile* self, wchar_t** out_String )\r
9171 {\r
9172         errnum_t  e;\r
9173 \r
9174         ASSERT_R( self->CharSize == 2, e=E_OTHERS; goto fin );\r
9175         *out_String = (wchar_t*)( (char*) self->Buffer + sizeof(wchar_t) );\r
9176 \r
9177         e=0;\r
9178 fin:\r
9179         return  e;\r
9180 }\r
9181 \r
9182 \r
9183 //[StrFile_peekWrittenStringA]\r
9184 errnum_t  StrFile_peekWrittenStringA( StrFile* self, char** out_String )\r
9185 {\r
9186         errnum_t  e;\r
9187 \r
9188         ASSERT_R( self->CharSize == 1, e=E_OTHERS; goto fin );\r
9189         *out_String = self->Buffer;\r
9190 \r
9191         e=0;\r
9192 fin:\r
9193         return  e;\r
9194 }\r
9195 \r
9196 \r
9197 //[StrFile_pickupSizedStruct]\r
9198 errnum_t  StrFile_pickupSizedStruct( StrFile* self, SizedStruct** out_Struct )\r
9199 {\r
9200         *out_Struct = (SizedStruct*)( (char*) self->Buffer - sizeof(size_t) );\r
9201         *( (size_t*) self->Buffer - 1 ) = (char*) self->Pointer - (char*) self->Buffer + sizeof(size_t);\r
9202         self->IsBufferInHeap = false;\r
9203         return  0;\r
9204 }\r
9205 \r
9206 \r
9207 //[StrFile_restoreSizedStruct]\r
9208 errnum_t  StrFile_restoreSizedStruct( StrFile* self, SizedStruct* Struct, errnum_t e )\r
9209 {\r
9210         ASSERT_R( ! self->IsBufferInHeap, goto err );\r
9211 \r
9212         self->Buffer = (char*) Struct + sizeof(size_t);\r
9213         self->IsBufferInHeap = true;\r
9214 \r
9215         e=0;\r
9216 fin:\r
9217         return  e;\r
9218 \r
9219 err:  e = E_OTHERS;  goto fin;\r
9220 }\r
9221 \r
9222 \r
9223 //[StrFile_moveSizedStructToStream]\r
9224 errnum_t  StrFile_moveSizedStructToStream( StrFile* self, HANDLE Stream )\r
9225 {\r
9226         errnum_t  e;\r
9227         SizedStruct*  data = NULL;\r
9228 \r
9229         e= StrFile_pickupSizedStruct( self, &data ); IF(e)goto fin;\r
9230         e= FileT_writeSizedStruct_WinAPI( Stream, data ); IF(e)goto fin;\r
9231         e=0;\r
9232 fin:\r
9233         if ( data != NULL )  { e= StrFile_restoreSizedStruct( self, data, e ); }\r
9234         return  e;\r
9235 }\r
9236 \r
9237 \r
9238 //[StrFile_setPointer]\r
9239 errnum_t  StrFile_setPointer( StrFile* self, int OffsetOfPointer )\r
9240 {\r
9241         if ( self->CharSize == 2 )  OffsetOfPointer += sizeof(wchar_t);\r
9242         IF( OffsetOfPointer < 0  ||  OffsetOfPointer >= (int) self->BufferSize ) return  E_INVALID_VALUE;\r
9243         self->Pointer = (char*) self->Buffer + OffsetOfPointer;\r
9244         return  0;\r
9245 }\r
9246 \r
9247 \r
9248 /*[StrFile_getPointer]*/\r
9249 errnum_t  StrFile_getPointer( StrFile* self, int* out_OffsetOfPointer )\r
9250 {\r
9251         if ( (uintptr_t) self->Pointer == 0xFFFFFFFF )\r
9252                 { *out_OffsetOfPointer = self->BufferSize; }\r
9253         else\r
9254                 { *out_OffsetOfPointer = (char*) self->Pointer - (char*) self->Buffer; }\r
9255         return  0;\r
9256 }\r
9257 \r
9258 \r
9259 //[StrFile_isAtEndOfStream]\r
9260 bool  StrFile_isAtEndOfStream( StrFile* self )\r
9261 {\r
9262         return  self->Pointer == (void*)0xFFFFFFFF;\r
9263 }\r
9264 \r
9265 \r
9266 //[StrFile_isInited]\r
9267 errnum_t  StrFile_isInited( StrFile* self )\r
9268 {\r
9269         return  self->Buffer != NULL;\r
9270 }\r
9271 \r
9272 \r
9273  \r
9274 /***********************************************************************\r
9275   <<< (SearchStringByBM_Class) >>> \r
9276 ************************************************************************/\r
9277 errnum_t  SearchStringByBM_Class_allocateSkipArray_Sub( SearchStringByBM_Class* self );\r
9278 \r
9279 \r
9280 /*[SearchStringByBM_Class_initConst]*/\r
9281 void  SearchStringByBM_Class_initConst( SearchStringByBM_Class* self )\r
9282 {\r
9283         self->SkipArray = NULL;\r
9284 }\r
9285 \r
9286 \r
9287 /*[SearchStringByBM_Class_initialize]*/\r
9288 errnum_t  SearchStringByBM_Class_initialize( SearchStringByBM_Class* self,\r
9289         const TCHAR* TextString,  const TCHAR* Keyword )\r
9290 {\r
9291         return  SearchStringByBM_Class_initializeFromPart( self,\r
9292                 TextString,  _tcslen( TextString ),  Keyword );\r
9293 }\r
9294 \r
9295 \r
9296 /*[SearchStringByBM_Class_initializeFromPart]*/\r
9297 errnum_t  SearchStringByBM_Class_initializeFromPart( SearchStringByBM_Class* self,\r
9298         const TCHAR* TextString,  size_t TextString_Length,  const TCHAR* Keyword )\r
9299 {\r
9300         self->TextString = TextString;\r
9301         self->TextStringLength = TextString_Length;\r
9302         self->Keyword = Keyword;\r
9303 \r
9304         /* \91¼\82Ì\83\81\83\93\83o\81[\95Ï\90\94\82Í\81A\8e\9f\82Ì\8aÖ\90\94\82Ì\92\86\82Å\8f\89\8aú\89»\82·\82é */\r
9305         return  SearchStringByBM_Class_allocateSkipArray_Sub( self );\r
9306 }\r
9307 \r
9308 \r
9309 /*[SearchStringByBM_Class_finalize]*/\r
9310 errnum_t  SearchStringByBM_Class_finalize( SearchStringByBM_Class* self, errnum_t e )\r
9311 {\r
9312         if ( self->SkipArray != NULL ) {\r
9313                 free( self->SkipArray );\r
9314                 self->SkipArray = NULL;\r
9315         }\r
9316 \r
9317         return  e;\r
9318 }\r
9319 \r
9320 \r
9321 /***********************************************************************\r
9322   <<< [SearchStringByBM_Class_getSkipCount_Sub] >>> \r
9323  - Boyer-Moore\96@\82Ì skip \8aÖ\90\94\r
9324 ************************************************************************/\r
9325 inline int  SearchStringByBM_Class_getSkipCount_Sub(\r
9326         TCHAR TextCharacter, int KeywordLastIndex,\r
9327         int* SkipArray, int SkipArray_MinCharacter, int SkipArray_MaxCharacter )\r
9328 {\r
9329         if (\r
9330                         TextCharacter < SkipArray_MinCharacter  ||\r
9331                         TextCharacter > SkipArray_MaxCharacter ) {\r
9332                 return  KeywordLastIndex + 1;\r
9333         }\r
9334         else {\r
9335                 return  SkipArray[ TextCharacter - SkipArray_MinCharacter ];\r
9336         }\r
9337 }\r
9338 \r
9339 \r
9340 /***********************************************************************\r
9341   <<< [SearchStringByBM_Class_search] >>> \r
9342  - Boyer-Moore\96@\r
9343  - \8fî\95ñ\8c\9f\8dõ\83A\83\8b\83S\83\8a\83Y\83\80 p106 \82Ì C\8c¾\8cê\94Å\r
9344 ************************************************************************/\r
9345 errnum_t  SearchStringByBM_Class_search( SearchStringByBM_Class* self, int* out_KeywordIndex )\r
9346 {\r
9347         const TCHAR*  test_string = self->TextString;\r
9348         const TCHAR*  keyword = self->Keyword;\r
9349         int           text_string_length = self->TextStringLength;        /* m */\r
9350         int           keyword_last_index = self->KeywordLastIndex;        /* n - 1 */\r
9351         int           keyword_last_position = self->KeywordLastPosition;  /* pos - 1 */\r
9352         int           skip_count;\r
9353         int*          skip_array = self->SkipArray;\r
9354         TCHAR         min_character = self->SkipArray_MinCharacter;\r
9355         TCHAR         max_character = self->SkipArray_MaxCharacter;\r
9356 \r
9357         *out_KeywordIndex = SearchString_NotFound;\r
9358 \r
9359 \r
9360         while ( keyword_last_position < text_string_length ) {\r
9361 \r
9362                 /* \8e\9f\82Ì\8fÆ\8d\87\88Ê\92u\82Ö (1) */\r
9363                 skip_count = SearchStringByBM_Class_getSkipCount_Sub(\r
9364                         test_string[ keyword_last_position ],\r
9365                         keyword_last_index,  skip_array,  min_character,  max_character );\r
9366 \r
9367 \r
9368                 /* \96\96\94ö\82Ì\8fÆ\8d\87\82ª\90¬\8c÷\82µ\82½\82ç */\r
9369                 if ( test_string[ keyword_last_position ] == keyword[ keyword_last_index ] ) {\r
9370 \r
9371                         /* \96\96\94ö\82©\82ç\8fÆ\8d\87\82·\82é */\r
9372                         int  text_string_index = keyword_last_position - 1;  /* k - 1 */\r
9373                         int  keyword_index = keyword_last_index - 1;         /* j - 1 */\r
9374 \r
9375                         for (;;) {\r
9376                                 /* \83L\81[\83\8f\81[\83h\91S\91Ì\82Ì\8fÆ\8d\87\82É\90¬\8c÷\82µ\82½\82ç */\r
9377                                 if ( keyword_index < 0 ) {\r
9378                                         *out_KeywordIndex = text_string_index + 1;\r
9379                                         self->KeywordLastPosition = keyword_last_position + skip_count;\r
9380                                         goto  fin;\r
9381                                 }\r
9382 \r
9383                                 /* \8fÆ\8d\87\82ª\8e¸\94s\82µ\82½\82ç */\r
9384                                 if ( test_string[ text_string_index ] != keyword[ keyword_index ] ) {\r
9385                                         break;\r
9386                                 }\r
9387 \r
9388                                 /* \82P\82Â\91O\82Ì\95\8e\9a\82Ö */\r
9389                                 text_string_index -= 1;\r
9390                                 keyword_index -= 1;\r
9391                         }\r
9392                 }\r
9393                 /* \8e\9f\82Ì\8fÆ\8d\87\88Ê\92u\82Ö (2) */\r
9394                 keyword_last_position += skip_count;\r
9395         }\r
9396 \r
9397 fin:\r
9398         return  0;\r
9399 }\r
9400 \r
9401 \r
9402 /***********************************************************************\r
9403   <<< [SearchStringByBM_Class_allocateSkipArray_Sub] >>> \r
9404  - Boyer-Moore\96@\82Ì skip \8aÖ\90\94\82ð\8dì\90¬\82·\82é\8aÖ\90\94\r
9405  - \8fî\95ñ\8c\9f\8dõ\83A\83\8b\83S\83\8a\83Y\83\80 p107 \82Ì C\8c¾\8cê\94Å\82Í\81A\89º\8bL Set "self->SkipArray" \88È\8d~\r
9406 ************************************************************************/\r
9407 errnum_t  SearchStringByBM_Class_allocateSkipArray_Sub( SearchStringByBM_Class* self )\r
9408 {\r
9409         const TCHAR*  keyword = self->Keyword;\r
9410         const TCHAR*  p;  /* Pointer to "keyword" */\r
9411         TCHAR         c;  /* Character in "keyword" */\r
9412         TCHAR         min_character;\r
9413         TCHAR         max_character;\r
9414         int           keyword_length;\r
9415         const TCHAR*  keyword_last_pointer;\r
9416         int*          skip_array = NULL;\r
9417         errnum_t      e;\r
9418 \r
9419 \r
9420         /* Set "self->SkipArray_MinCharacter", "self->SkipArray_MaxCharacter" */\r
9421         c = *keyword;\r
9422         IF ( c == _T('\0') ) { e=E_OTHERS; goto fin; }\r
9423         min_character = c;\r
9424         max_character = c;\r
9425         p = keyword + 1;\r
9426         for (;;) {\r
9427                 c = *p;\r
9428                 if ( c == _T('\0') ) { break; }\r
9429 \r
9430                 if ( c < min_character ) { min_character = c; }\r
9431                 if ( c > max_character ) { max_character = c; }\r
9432 \r
9433                 p += 1;\r
9434         }\r
9435         self->SkipArray_MinCharacter = min_character;\r
9436         self->SkipArray_MaxCharacter = max_character;\r
9437 \r
9438 \r
9439         /* Set ... */\r
9440         keyword_length            = p - keyword;\r
9441         self->KeywordLastIndex    = keyword_length - 1;\r
9442         self->KeywordLastPosition = keyword_length - 1;\r
9443 \r
9444 \r
9445         /* Set "self->SkipArray" */\r
9446         skip_array = malloc( ( max_character - min_character + 1 ) * sizeof(int) );\r
9447                 IF ( skip_array == NULL ) { e=E_FEW_ARRAY; goto fin; }\r
9448 \r
9449         for ( c = min_character;  c <= max_character;  c += 1 ) {\r
9450                 /* \83L\81[\83\8f\81[\83h\82É\8eg\82í\82ê\82Ä\82¢\82È\82¢\95\8e\9a\82É\82Â\82¢\82Ä */\r
9451                 skip_array[ c - min_character ] = keyword_length;\r
9452         }\r
9453 \r
9454         keyword_last_pointer = &keyword[ keyword_length - 1 ];\r
9455         for (\r
9456                 p = keyword;\r
9457                 p < keyword_last_pointer;\r
9458                 p += 1 ) {\r
9459 \r
9460                 /* \83L\81[\83\8f\81[\83h\82É\8eg\82í\82ê\82Ä\82¢\82é\95\8e\9a\82É\82Â\82¢\82Ä */\r
9461                 /* \83L\81[\83\8f\81[\83h\82Ì\92\86\82É\93¯\82\95\8e\9a\82ª\82 \82é\82Æ\82«\82Í\81A\8cã\82ë\82Ì\95\8e\9a\82Ì\88Ê\92u\82ª\97D\90æ\82³\82ê\82é */\r
9462                 skip_array[ *p - min_character ] = keyword_last_pointer - p;\r
9463         }\r
9464 \r
9465 \r
9466         e=0;\r
9467 fin:\r
9468         if (e) {\r
9469                 if ( skip_array != NULL ) {\r
9470                         free( skip_array );\r
9471                         skip_array = NULL;\r
9472                 }\r
9473         }\r
9474         self->SkipArray = skip_array;\r
9475         return  e;\r
9476 }\r
9477 \r
9478 \r
9479  \r
9480 /***********************************************************************\r
9481   <<< (SearchStringByAC_Class) >>> \r
9482 ************************************************************************/\r
9483 errnum_t  SearchStringByAC_Class_makeFunctionsStep1( SearchStringByAC_Class* self,\r
9484         const TCHAR** KeywordArray, unsigned KeywordArrayCount );\r
9485 errnum_t  SearchStringByAC_Class_makeFunctionsStep2( SearchStringByAC_Class* self );\r
9486 errnum_t  SearchStringByAC_Class_increaseState( SearchStringByAC_Class* self );\r
9487 errnum_t  SearchStringByAC_Class_addOutputFunction( SearchStringByAC_Class* self,\r
9488         int State, const TCHAR* Keyword );\r
9489 errnum_t  SearchStringByAC_Class_addOutputFunctions( SearchStringByAC_Class* self,\r
9490         int TargetState, int SourceState );\r
9491 \r
9492 \r
9493 /***********************************************************************\r
9494   <<< [SearchStringByAC_Class_initConst] >>> \r
9495 ************************************************************************/\r
9496 void  SearchStringByAC_Class_initConst( SearchStringByAC_Class* self )\r
9497 {\r
9498         Set2_initConst( &self->GoToFunction );\r
9499         self->FailureFunction = NULL;\r
9500         self->OutputFunction = NULL;\r
9501         self->OutputCount = NULL;\r
9502 }\r
9503 \r
9504 \r
9505 /***********************************************************************\r
9506   <<< [SearchStringByAC_Class_initialize] >>> \r
9507 ************************************************************************/\r
9508 errnum_t  SearchStringByAC_Class_initialize( SearchStringByAC_Class* self,\r
9509         const TCHAR* TextString, const TCHAR** KeywordArray, size_t KeywordArrayCount )\r
9510 {\r
9511         return  SearchStringByAC_Class_initializeFromPart(\r
9512                 self, TextString, _tcslen( TextString ), KeywordArray, KeywordArrayCount );\r
9513 }\r
9514 \r
9515 \r
9516 /***********************************************************************\r
9517   <<< [SearchStringByAC_Class_initializeFromPart] >>> \r
9518 ************************************************************************/\r
9519 errnum_t  SearchStringByAC_Class_initializeFromPart( SearchStringByAC_Class* self,\r
9520         const TCHAR* TextString,  size_t TextString_Length,\r
9521         const TCHAR** KeywordArray,  size_t KeywordArrayCount )\r
9522 {\r
9523         errnum_t  e;\r
9524 \r
9525         self->StateNum = SearchStringByAC_RootState;\r
9526         self->TextString = TextString;\r
9527         self->TextStringLength = TextString_Length;\r
9528         self->TextStringIndex = 0;\r
9529         self->FoundKeywords = NULL;\r
9530 \r
9531         e= Set2_init( &self->GoToFunction, 0x1000 ); IF(e){goto fin;}\r
9532         self->FailureFunction = NULL;\r
9533         self->OutputFunction = NULL;\r
9534         self->OutputCount = NULL;\r
9535         self->StateCount = 0;\r
9536 \r
9537         /* Make functions */\r
9538         e= SearchStringByAC_Class_makeFunctionsStep1( self, KeywordArray, KeywordArrayCount );\r
9539                 IF(e){goto fin;}\r
9540         e= SearchStringByAC_Class_makeFunctionsStep2( self );\r
9541                 IF(e){goto fin;}\r
9542 \r
9543         e=0;\r
9544 fin:\r
9545         if (e) {\r
9546                 SearchStringByAC_Class_finalize( self, e );\r
9547         }\r
9548         return  e;\r
9549 }\r
9550 \r
9551 \r
9552 /***********************************************************************\r
9553   <<< [SearchStringByAC_Class_finalize] >>> \r
9554 ************************************************************************/\r
9555 errnum_t  SearchStringByAC_Class_finalize( SearchStringByAC_Class* self, errnum_t e )\r
9556 {\r
9557         e= Set2_finish( &self->GoToFunction, e );\r
9558 \r
9559         if ( self->FailureFunction != NULL ) {\r
9560                 free( self->FailureFunction );\r
9561                 self->FailureFunction = NULL;\r
9562         }\r
9563         if ( self->OutputFunction != NULL ) {\r
9564                 int  i;\r
9565 \r
9566                 for ( i = 0;  i < self->StateCount; i += 1 ) {\r
9567                         const TCHAR**  keywords = self->OutputFunction[i];\r
9568                                 \r
9569                         if ( keywords != NULL ) {\r
9570                                 free( (void*) keywords );\r
9571                         }\r
9572                 }\r
9573                 free( (void*) self->OutputFunction );\r
9574                 self->OutputFunction = NULL;\r
9575         }\r
9576         if ( self->OutputCount != NULL ) {\r
9577                 free( self->OutputCount );\r
9578                 self->OutputCount = NULL;\r
9579         }\r
9580         return  e;\r
9581 }\r
9582 \r
9583 \r
9584 /***********************************************************************\r
9585   <<< [SearchStringByAC_Class_search] >>> \r
9586  - Aho-Corasick\96@(AC\96@)\82Ì\8c\9f\8dõ\82ð\82·\82é\8aÖ\90\94\r
9587  - \8fî\95ñ\8c\9f\8dõ\83A\83\8b\83S\83\8a\83Y\83\80 p112 \82Ì C\8c¾\8cê\94Å\82Í\81A\96{\8aÖ\90\94\82Ì for \95\88È\8d~\r
9588 ************************************************************************/\r
9589 errnum_t  SearchStringByAC_Class_search( SearchStringByAC_Class* self,\r
9590         int* out_TextStringIndex, TCHAR** out_Keyword )\r
9591 {\r
9592         int                  state_num = self->StateNum;                   /* s */\r
9593         const TCHAR*         text_string = self->TextString;               /* text */\r
9594         int                  text_string_length = self->TextStringLength;  /* m */\r
9595         int                  text_string_index = self->TextStringIndex;    /* i - 1 */\r
9596         AC_GotoFunctionType  goto_function = (AC_GotoFunctionType) self->GoToFunction.First;  /* g */\r
9597         int*                 failure_function = self->FailureFunction;     /* f */\r
9598         const TCHAR***       output_function = self->OutputFunction;       /* output */\r
9599         int                  next_state_num;\r
9600         const TCHAR**        found_keywords = self->FoundKeywords;\r
9601         errnum_t             e;\r
9602 \r
9603 \r
9604         /* \91O\89ñ\83}\83b\83`\82µ\82½\83L\81[\83\8f\81[\83h\82Ì\91±\82«\82ð\8fo\97Í\82·\82é */\r
9605         if ( found_keywords != NULL ) {\r
9606                 int           found_keyword_index = self->FoundKeywordIndex + 1;\r
9607                 const TCHAR*  keyword;\r
9608 \r
9609                 if ( found_keyword_index < self->FoundKeywordsCount ) {\r
9610                         keyword = found_keywords[ found_keyword_index ];\r
9611 \r
9612                         *out_Keyword = (TCHAR*) keyword;\r
9613                         *out_TextStringIndex = text_string_index + 1 - _tcslen( keyword );\r
9614                         self->FoundKeywordIndex = found_keyword_index;\r
9615                         return  0;\r
9616                 }\r
9617                 self->FoundKeywords = NULL;\r
9618                 text_string_index += 1;\r
9619         }\r
9620 \r
9621         /* \83e\83L\83X\83g\82Ì\92\86\82ð\82P\95\8e\9a\82¸\82Â\92²\82×\82é */\r
9622         for ( /* "text_string_index" is already set */;\r
9623                         text_string_index < text_string_length;\r
9624                         text_string_index += 1 ) {\r
9625 \r
9626                 for (;;) {\r
9627                         TCHAR  a_character = text_string[ text_string_index ];\r
9628 \r
9629                         /* AC\96@\82Ì goto \8aÖ\90\94\82ð\8eg\82Á\82Ä\81A\8e\9f\82Ì\8fó\91Ô\82É\91J\88Ú\82·\82é */\r
9630 #if 0\r
9631                         ASSERT_R( text_string[ text_string_index ] <= SearchStringByAC_MaxCharacterCode,\r
9632                                 e=E_OTHERS; goto fin );\r
9633 #else\r
9634 if ( a_character > SearchStringByAC_MaxCharacterCode ) {\r
9635         a_character = _T('\0');\r
9636 }\r
9637 #endif\r
9638                         next_state_num = goto_function[ state_num ][ a_character ];\r
9639 \r
9640                         /* AC\96@\82Ì goto \8aÖ\90\94\82ª fail \82µ\82½\82ç\81Afailure \8aÖ\90\94\82ð\8eg\82Á\82Ä\81A */\r
9641                         /* \8e\9f\82Ì\8fó\91Ô\82É\91J\88Ú\82µ\82Ä\81A\8dÄ\82Ñ goto \8aÖ\90\94\82ð\8eg\82¤ */\r
9642                         if ( next_state_num == SearchStringByAC_Fail ) {\r
9643                                 if ( state_num == SearchStringByAC_RootState ) {\r
9644                                         next_state_num = SearchStringByAC_RootState;\r
9645                                         break;\r
9646                                 }\r
9647                                 state_num = failure_function[ state_num ];\r
9648                         }\r
9649                         else\r
9650                                 { break; }\r
9651                 }\r
9652                 state_num = next_state_num;\r
9653 \r
9654                 /* AC\96@\82Ì output \8aÖ\90\94\82ð\8eg\82Á\82Ä\81A\83}\83b\83`\82µ\82½\83L\81[\83\8f\81[\83h\82ð\8fo\97Í\82·\82é */\r
9655                 found_keywords = output_function[ state_num ];\r
9656                 if ( found_keywords != NULL ) {\r
9657                         const int     first_keyword_index = 0;\r
9658                         const TCHAR*  keyword = found_keywords[ first_keyword_index ];\r
9659 \r
9660                         *out_Keyword = (TCHAR*) keyword;\r
9661                         *out_TextStringIndex = text_string_index + 1 - _tcslen( keyword );\r
9662                         self->FoundKeywords = found_keywords;\r
9663                         self->FoundKeywordsCount = self->OutputCount[ state_num ];\r
9664                         self->FoundKeywordIndex = first_keyword_index;\r
9665                         self->TextStringIndex = text_string_index;\r
9666                         self->StateNum = state_num;\r
9667                         e=0; goto fin;\r
9668                 }\r
9669         }\r
9670 \r
9671         /* \83e\83L\83X\83g\82Ì\8dÅ\8cã\82Ü\82Å\92²\82×\82½\8cã */\r
9672         *out_Keyword = NULL;\r
9673         *out_TextStringIndex = SearchString_NotFound;\r
9674         self->FoundKeywords = NULL;\r
9675 \r
9676         e=0;\r
9677 fin:\r
9678         return  e;\r
9679 }\r
9680 \r
9681 \r
9682 /***********************************************************************\r
9683   <<< [SearchStringByAC_Class_setTextString] >>> \r
9684 ************************************************************************/\r
9685 errnum_t  SearchStringByAC_Class_setTextString( SearchStringByAC_Class* self,\r
9686         const TCHAR* TextString )\r
9687 {\r
9688         return  SearchStringByAC_Class_setTextStringFromPart( self,\r
9689                 TextString, _tcslen( TextString ) );\r
9690 }\r
9691 \r
9692 \r
9693 /***********************************************************************\r
9694   <<< [SearchStringByAC_Class_setTextStringFromPart] >>> \r
9695 ************************************************************************/\r
9696 errnum_t  SearchStringByAC_Class_setTextStringFromPart( SearchStringByAC_Class* self,\r
9697         const TCHAR* TextString,  size_t TextString_Length )\r
9698 {\r
9699         self->StateNum = SearchStringByAC_RootState;\r
9700         self->TextString = TextString;\r
9701         self->TextStringLength = TextString_Length;\r
9702         self->TextStringIndex = 0;\r
9703         self->FoundKeywords = NULL;\r
9704 \r
9705         return  0;\r
9706 }\r
9707 \r
9708 \r
9709 /***********************************************************************\r
9710   <<< [SearchStringByAC_Class_makeFunctionsStep1] >>> \r
9711  - Aho-Corasick\96@(AC\96@)\82Ì goto \8aÖ\90\94\82Æ output \8aÖ\90\94\82ð\8dì\90¬\82·\82é\r
9712  - \8fî\95ñ\8c\9f\8dõ\83A\83\8b\83S\83\8a\83Y\83\80 p117 \82Ì C\8c¾\8cê\94Å\r
9713 ************************************************************************/\r
9714 errnum_t  SearchStringByAC_Class_makeFunctionsStep1( SearchStringByAC_Class* self,\r
9715         const TCHAR** KeywordArray, unsigned KeywordArrayCount )\r
9716 {\r
9717         errnum_t  e;\r
9718         unsigned  keyword_num;\r
9719 \r
9720         AC_GotoFunctionType  goto_function;  /* g */\r
9721 \r
9722         e= SearchStringByAC_Class_increaseState( self ); IF(e){goto fin;}\r
9723                 /* newstate = 0; */ /* self->StateCount - 1 */\r
9724         goto_function = (AC_GotoFunctionType) self->GoToFunction.First;  /* g */\r
9725 \r
9726         for ( keyword_num = 0;  keyword_num < KeywordArrayCount;  keyword_num += 1 ) {\r
9727                 const TCHAR*  keyword = KeywordArray[ keyword_num ];\r
9728                 int  keyword_length = _tcslen( keyword );  /* n */\r
9729                 int  keyword_index;  /* j - 1, p - 1 */\r
9730                 int  state;\r
9731                 int  next_state;\r
9732 \r
9733                 state = SearchStringByAC_RootState;\r
9734                 keyword_index = 0;\r
9735 \r
9736                 /* \8aù\82É\93o\98^\82³\82ê\82Ä\82¢\82é goto \8aÖ\90\94\82Í\90V\82½\82É\92è\8b`\82µ\82È\82¢ */\r
9737                 for (;;) {\r
9738                         ASSERT_R( keyword[ keyword_index ] <= SearchStringByAC_MaxCharacterCode,\r
9739                                 e=E_OTHERS; goto fin );\r
9740                         next_state = goto_function[ state ][ keyword[ keyword_index ] ];\r
9741                         if ( next_state != SearchStringByAC_Fail ) {\r
9742                                 state = next_state;\r
9743                                 keyword_index += 1;\r
9744                         }\r
9745                         else\r
9746                                 { break; }\r
9747                 }\r
9748 \r
9749                 /* \90V\82µ\82¢\8fó\91Ô\82Ö\91J\88Ú\82·\82é goto \8aÖ\90\94\82ð\92è\8b`\82·\82é */\r
9750                 while ( keyword_index < keyword_length ) {\r
9751                         int16_t  new_state = self->StateCount;\r
9752 \r
9753                         e= SearchStringByAC_Class_increaseState( self );\r
9754                                 /* newstate += 1; */\r
9755                                 IF(e){goto fin;}\r
9756                         goto_function = (AC_GotoFunctionType) self->GoToFunction.First;  /* g */\r
9757                         ASSERT_R( keyword[ keyword_index ] <= SearchStringByAC_MaxCharacterCode,\r
9758                                 e=E_OTHERS; goto fin );\r
9759                         goto_function[ state ][ keyword[ keyword_index ] ] = new_state;\r
9760                         state = new_state;\r
9761                         keyword_index += 1;\r
9762                 }\r
9763                 e= SearchStringByAC_Class_addOutputFunction( self, state, keyword );\r
9764                         IF(e){goto fin;}\r
9765         }\r
9766 \r
9767         e=0;\r
9768 fin:\r
9769         return  e;\r
9770 }\r
9771 \r
9772 \r
9773 /***********************************************************************\r
9774   <<< [SearchStringByAC_Class_makeFunctionsStep2] >>> \r
9775  - Aho-Corasick\96@(AC\96@)\82Ì failure \8aÖ\90\94\82Ì\8dì\90¬\82Æ output \8aÖ\90\94\82Ì\8dX\90V\82ð\82·\82é\r
9776  - \8fî\95ñ\8c\9f\8dõ\83A\83\8b\83S\83\8a\83Y\83\80 p122 \82Ì C\8c¾\8cê\94Å\r
9777 ************************************************************************/\r
9778 errnum_t  SearchStringByAC_Class_makeFunctionsStep2( SearchStringByAC_Class* self )\r
9779 {\r
9780         errnum_t  e;\r
9781         uint32_t  ch;          /* Character(\95\8e\9a) TCHAR\8c^\82É\82µ\82È\82¢\82Ì\82Í\81A\83\8b\81[\83v\82ð\8fI\97¹\82³\82¹\82é\82½\82ß */\r
9782         int    state;          /* s */\r
9783         int*   queue = NULL;\r
9784         int    enqueue_index;\r
9785         int    dequeue_index;\r
9786         int*   failure_function = NULL;\r
9787         AC_GotoFunctionType  goto_function = (AC_GotoFunctionType) self->GoToFunction.First;\r
9788 \r
9789 \r
9790         /* \83L\83\85\81[\82ð\8f\89\8aú\89»\82·\82é */\r
9791         queue = (int*) malloc( sizeof(int) * self->StateCount );\r
9792                 IF( queue == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
9793         enqueue_index = 0;\r
9794         dequeue_index = 0;\r
9795 \r
9796         /* failure \8aÖ\90\94\82ð\8f\89\8aú\89»\82·\82é */\r
9797         failure_function = (int*) malloc( sizeof(int) * self->StateCount );\r
9798                 IF( failure_function == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
9799 \r
9800         /* \90[\82³\82ª\82P\82Ì failure \8aÖ\90\94\82Ì\8fo\97Í\82ð\82O\82É\82·\82é */\r
9801         for ( ch = 0;  ch <= SearchStringByAC_MaxCharacterCode;  ch += 1 ) {\r
9802                 state = goto_function[ SearchStringByAC_RootState ][ ch ];\r
9803                 if ( state == SearchStringByAC_Fail ) { continue; }\r
9804 \r
9805                 \r
9806                 /* \8fó\91Ô 0(=SearchStringByAC_RootState) \82Ì\91J\88Ú\90æ\82Ì\8fó\91Ô\82ð\83L\83\85\81[\82É\92Ç\89Á\82·\82é */\r
9807                 queue[ enqueue_index ] = state;\r
9808                 enqueue_index += 1;\r
9809 \r
9810                 failure_function[ state ] = SearchStringByAC_RootState;\r
9811         }\r
9812 \r
9813         while ( enqueue_index > dequeue_index ) {\r
9814                 int  back_state;      /* r */\r
9815                 int  back_new_state;  /* state, p */\r
9816                 int  new_state;       /* q */\r
9817 \r
9818                 /* \83L\83\85\81[\82©\82ç\8eæ\82è\8fo\82µ\82½\8fó\91Ô\82ð\81A\82P\82Â\90ó\82¢\8fó\91Ô r \82Æ\82·\82é */\r
9819                 back_state = queue[ dequeue_index ];\r
9820                 dequeue_index += 1;\r
9821 \r
9822                 for ( ch = 0;  ch <= SearchStringByAC_MaxCharacterCode;  ch += 1 ) {\r
9823                         state = goto_function[ back_state ][ ch ];\r
9824                         if ( state == SearchStringByAC_Fail ) { continue; }\r
9825 \r
9826                         /* back_state \82Ì\91J\88Ú\90æ\82Ì\8fó\91Ô\82ð\83L\83\85\81[\82É\92Ç\89Á\82·\82é */\r
9827                         queue[ enqueue_index ] = state;\r
9828                         enqueue_index += 1;\r
9829 \r
9830                         /* 0\81`state \82©\82ç\82È\82é\95\8e\9a\97ñ\82Ì\81A\8dÅ\92·\82Ì\90Ú\94ö\8e« 0\81`new_state \82ð\92T\82· */\r
9831                         back_new_state = failure_function[ back_state ];\r
9832                         for (;;) {\r
9833                                 new_state = goto_function[ back_new_state ][ ch ];\r
9834                                 if ( new_state == SearchStringByAC_Fail ) {\r
9835                                         if ( back_new_state == SearchStringByAC_RootState ) {\r
9836                                                 new_state = SearchStringByAC_RootState;\r
9837                                                 break;\r
9838                                         }\r
9839                                         back_new_state = failure_function[ back_new_state ];\r
9840                                 }\r
9841                                 else\r
9842                                         { break; }\r
9843                         }\r
9844                         failure_function[ state ] = new_state;\r
9845 \r
9846                         /* output \8aÖ\90\94\82ð\8dX\90V\82·\82é */\r
9847                         e= SearchStringByAC_Class_addOutputFunctions(\r
9848                                 self, state, failure_function[ state ] );\r
9849                                 IF(e){goto fin;}\r
9850                 }\r
9851         }\r
9852 \r
9853         self->FailureFunction = failure_function;\r
9854         failure_function = NULL;\r
9855 \r
9856         e=0;\r
9857 fin:\r
9858         if ( queue != NULL ) { free( queue ); }\r
9859         if ( failure_function != NULL ) { free( failure_function ); }\r
9860         return  e;\r
9861 }\r
9862 \r
9863 \r
9864 /***********************************************************************\r
9865   <<< [SearchStringByAC_Class_increaseState] >>> \r
9866 ************************************************************************/\r
9867 errnum_t  SearchStringByAC_Class_increaseState( SearchStringByAC_Class* self )\r
9868 {\r
9869         errnum_t  e;\r
9870         AC_GotoFunctionType  new_goto_function;\r
9871         const TCHAR***       new_output_function;\r
9872         int*                 new_output_count;\r
9873         int16_t              new_state_count = self->StateCount + 1;\r
9874 \r
9875 \r
9876         /* goto \8aÖ\90\94\82É\91\8a\93\96\82·\82é\83\81\83\82\83\8a\81[\97Ì\88æ\82ð\91\9d\82â\82· */\r
9877         e= Set2_allocate( &self->GoToFunction, &new_goto_function ); IF(e){goto fin;}\r
9878 #if 0 //[TODO]\r
9879 printf( "goto funcion  %d/%d \n",\r
9880 Set2_getCount(    &self->GoToFunction, *new_goto_function ),\r
9881 Set2_getCountMax( &self->GoToFunction, *new_goto_function ) );\r
9882 #endif\r
9883 \r
9884         /* \90V\82µ\82¢ state \82Ì goto \8aÖ\90\94\82ð 0(=SearchStringByAC_Fail) \82Å\8f\89\8aú\89»\82·\82é */\r
9885         memset( new_goto_function, 0, sizeof(*new_goto_function) );\r
9886 \r
9887 \r
9888         /* output \8aÖ\90\94\82É\91\8a\93\96\82·\82é\83\81\83\82\83\8a\81[\97Ì\88æ\82ð\91\9d\82â\82· */\r
9889         new_output_function = (const TCHAR***) realloc( (void*) self->OutputFunction,\r
9890                 sizeof(self->OutputFunction[0]) * new_state_count );\r
9891                 IF ( new_output_function == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
9892         new_output_function[ new_state_count - 1 ] = NULL;\r
9893 \r
9894         new_output_count = (int*) realloc( self->OutputCount,\r
9895                 sizeof(self->OutputCount[0]) * new_state_count );\r
9896                 IF ( new_output_count == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
9897         new_output_count[ new_state_count - 1 ] = 0;\r
9898 \r
9899 \r
9900         /* Set "self->..." */\r
9901         self->OutputFunction = new_output_function;\r
9902         self->OutputCount    = new_output_count;\r
9903         self->StateCount     = new_state_count;\r
9904 \r
9905         e=0;\r
9906 fin:\r
9907         return  e;\r
9908 }\r
9909 \r
9910 \r
9911 /***********************************************************************\r
9912   <<< [SearchStringByAC_Class_addOutputFunction] >>> \r
9913 ************************************************************************/\r
9914 errnum_t  SearchStringByAC_Class_addOutputFunction( SearchStringByAC_Class* self,\r
9915         int State, const TCHAR* Keyword )\r
9916 {\r
9917         errnum_t       e;\r
9918         const TCHAR**  new_keywords = NULL;\r
9919         int            old_count = self->OutputCount[ State ];\r
9920 \r
9921         new_keywords = (const TCHAR**) realloc( (void*) self->OutputFunction[ State ],\r
9922                 sizeof(const TCHAR*) * (old_count + 1) );\r
9923                 IF ( new_keywords == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
9924         new_keywords[ old_count ] = Keyword;\r
9925 \r
9926         self->OutputFunction[ State ] = new_keywords;\r
9927         self->OutputCount[ State ] = old_count + 1;\r
9928 \r
9929         e=0;\r
9930 fin:\r
9931         return  e;\r
9932 }\r
9933 \r
9934 \r
9935 /***********************************************************************\r
9936   <<< [SearchStringByAC_Class_addOutputFunctions] >>> \r
9937 ************************************************************************/\r
9938 errnum_t  SearchStringByAC_Class_addOutputFunctions( SearchStringByAC_Class* self,\r
9939         int TargetState, int SourceState )\r
9940 {\r
9941         errnum_t       e;\r
9942         const TCHAR**  keywords = self->OutputFunction[ SourceState ];\r
9943         int            i;\r
9944         int            count = self->OutputCount[ SourceState ];\r
9945 \r
9946         for ( i = 0;  i < count;  i += 1 ) {\r
9947                 e= SearchStringByAC_Class_addOutputFunction( self,\r
9948                         TargetState, keywords[ i ] );\r
9949                         IF(e){goto fin;}\r
9950         }\r
9951 \r
9952         e=0;\r
9953 fin:\r
9954         return  e;\r
9955 }\r
9956 \r
9957 \r
9958  \r
9959 /*=================================================================*/\r
9960 /* <<< [DebugTools/DebugTools.c] >>> */ \r
9961 /*=================================================================*/\r
9962  \r
9963 /**************************************************************************\r
9964   <<< (g_DebugVar) >>> \r
9965 ***************************************************************************/\r
9966 int  g_DebugVar[10];\r
9967 \r
9968 \r
9969  \r
9970 /**************************************************************************\r
9971   <<< (DebugTools) >>> \r
9972 ***************************************************************************/\r
9973 #if DEBUGTOOLS_USES\r
9974 #define  DebugTools_get() (&g_DebugTools)\r
9975 extern  DebugTools  g_DebugTools;\r
9976 \r
9977 \r
9978 DebugTools  g_DebugTools;\r
9979 \r
9980 \r
9981 int  Debug_setReturnValueOnBreak( int ID )\r
9982 {\r
9983         DebugTools*  m = DebugTools_get();\r
9984         m->m_ReturnValueOnBreak_minus1 = ID - 1;\r
9985         return  0;\r
9986 }\r
9987 \r
9988 int  Debug_disableBreak( int iExceptID )\r
9989 {\r
9990         DebugTools*  m = DebugTools_get();\r
9991         m->m_DisableBreakExceptID_plus1 = iExceptID + 1;\r
9992         return  0;\r
9993 }\r
9994 \r
9995 int  Debug_setBreakByFName( const TCHAR* Path )\r
9996 {\r
9997         DebugTools*  m = DebugTools_get();\r
9998         return  MallocAndCopyString( &m->m_BreakByFName, Path );\r
9999 }\r
10000 \r
10001 int  Debug_onBreakCase( DebugTools* m )\r
10002 {\r
10003         m->m_BreakID ++;\r
10004         if ( m->m_DisableBreakExceptID_plus1 == 0 || m->m_BreakID == m->m_DisableBreakExceptID_plus1 - 1 ) {\r
10005                 // DebugBreakR();\r
10006                 if ( m->m_ReturnValueOnBreak_minus1 == 0 )  return  E_DEBUG_BREAK;\r
10007                 return  m->m_ReturnValueOnBreak_minus1 + 1;\r
10008         }\r
10009         else {\r
10010                 _tprintf( _T("[BREAK]\n") );\r
10011                 return 0;\r
10012         }\r
10013 }\r
10014 \r
10015 \r
10016 TCHAR*  StrT_refFName( const TCHAR* s );\r
10017 \r
10018 int  Debug_onOpen( const TCHAR* Path )\r
10019 {\r
10020         DebugTools*  m = DebugTools_get();\r
10021 \r
10022         if ( m->m_BreakByFName != NULL &&\r
10023                          _tcsicmp( m->m_BreakByFName, StrT_refFName( Path ) ) == 0 ) {\r
10024                 return  Debug_onBreakCase( m );\r
10025         }\r
10026         return  0;\r
10027 }\r
10028 \r
10029 #endif\r
10030 \r
10031  \r
10032 /***********************************************************************\r
10033   <<< [HeapLogWatchClass] >>> \r
10034 ************************************************************************/\r
10035 typedef struct _HeapLogWatchClass  HeapLogWatchClass;\r
10036 struct _HeapLogWatchClass {\r
10037         int        AllocatedID;\r
10038         ptrdiff_t  Offset;\r
10039         uint32_t   BreakValue;\r
10040         bool       IsPrintf;\r
10041         bool       IsEnabled;\r
10042 };\r
10043 HeapLogWatchClass  g_HeapLogWatch[ 10 ];\r
10044 \r
10045 \r
10046 /***********************************************************************\r
10047   <<< (HeapLogClass) >>> \r
10048 ************************************************************************/\r
10049 typedef struct _HeapLogClass  HeapLogClass;\r
10050 struct _HeapLogClass {\r
10051         void**   Addresses;\r
10052         size_t*  Sizes;\r
10053         int      Count;\r
10054         int      CountMax;\r
10055 };\r
10056 \r
10057 HeapLogClass  g_HeapLog;\r
10058 \r
10059 \r
10060 /***********************************************************************\r
10061   <<< [HeapLogClass_log] >>> \r
10062 ************************************************************************/\r
10063 void  HeapLogClass_log( void*  in_Address,  size_t  in_Size )\r
10064 {\r
10065         errnum_t  e;\r
10066         int       i;\r
10067 \r
10068         while ( g_HeapLog.Count >= g_HeapLog.CountMax ) {\r
10069                 void*  new_address;\r
10070                 int    new_count_max = g_HeapLog.CountMax * 2 + 4;\r
10071 \r
10072                 new_address = realloc_no_redirected( g_HeapLog.Addresses,  new_count_max * sizeof( *g_HeapLog.Addresses ) );\r
10073                 if ( new_address == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
10074                 g_HeapLog.Addresses = (void**) new_address;\r
10075 \r
10076                 new_address = realloc_no_redirected( g_HeapLog.Sizes,  new_count_max * sizeof( *g_HeapLog.Sizes ) );\r
10077                 if ( new_address == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
10078                 g_HeapLog.Sizes = (size_t*) new_address;\r
10079 \r
10080                 g_HeapLog.CountMax = new_count_max;\r
10081         }\r
10082 \r
10083         g_HeapLog.Addresses[ g_HeapLog.Count ] = in_Address;\r
10084         g_HeapLog.Sizes[     g_HeapLog.Count ] = in_Size;\r
10085         g_HeapLog.Count += 1;\r
10086 \r
10087 \r
10088         for ( i = 0;  i < _countof( g_HeapLogWatch );  i += 1 ) {\r
10089                 HeapLogWatchClass*  watch = &g_HeapLogWatch[ i ];\r
10090 \r
10091                 if ( watch->IsEnabled ) {\r
10092                         if ( watch->AllocatedID == g_HeapLog.Count ) {\r
10093                                 if ( watch->IsPrintf ) {\r
10094                                         printf( "<HeapLogClass_log  event=\"Allocated\"  index=\"%d\"/>\n",\r
10095                                                 i );\r
10096                                 }\r
10097                         }\r
10098                 }\r
10099         }\r
10100 \r
10101 fin:\r
10102         return;\r
10103 }\r
10104 \r
10105 \r
10106 /***********************************************************************\r
10107   <<< [HeapLogClass_getID] >>> \r
10108 ************************************************************************/\r
10109 int   HeapLogClass_getID( const void*  in_Address )\r
10110 {\r
10111         int  i;\r
10112 \r
10113         for ( i = g_HeapLog.Count - 1;  i >= 0;  i -= 1 ) {\r
10114                 const void*  start = g_HeapLog.Addresses[ i ];\r
10115                 const void*  over;\r
10116 \r
10117                 over = g_HeapLog.Addresses[ i ];\r
10118                 PointerType_plus( &over, g_HeapLog.Sizes[ i ] );\r
10119 \r
10120                 if ( start <= in_Address  &&  in_Address < over ) {\r
10121                         break;\r
10122                 }\r
10123         }\r
10124         return  i;\r
10125 }\r
10126 \r
10127 \r
10128 /***********************************************************************\r
10129   <<< [HeapLogClass_printID] >>> \r
10130 ************************************************************************/\r
10131 void   HeapLogClass_printID( const void*  in_Address )\r
10132 {\r
10133         int        block_ID = HeapLogClass_getID( in_Address );\r
10134         ptrdiff_t  offset;\r
10135 \r
10136         if ( block_ID != HeapLogClass_NotAllocatedID ) {\r
10137                 offset = PointerType_diff( in_Address, g_HeapLog.Addresses[ block_ID ] );\r
10138         }\r
10139         else {\r
10140                 offset = 0;\r
10141         }\r
10142 \r
10143         printf( "<HeapLogClass_printID  allocated_id=\"%d\"  offset=\"0x%04X\"/>\n",\r
10144                 block_ID,  offset );\r
10145 }\r
10146 \r
10147 \r
10148 /***********************************************************************\r
10149   <<< [HeapLogClass_addWatch] >>> \r
10150 ************************************************************************/\r
10151 void  HeapLogClass_addWatch( int  in_IndexNum,  int  in_AllocatedID,  ptrdiff_t  in_Offset,\r
10152         uint32_t  in_BreakValue,  bool  in_IsPrintf )\r
10153 {\r
10154         HeapLogWatchClass*  watch = &g_HeapLogWatch[ in_IndexNum ];\r
10155 \r
10156         if ( in_IndexNum >= _countof( g_HeapLogWatch ) ) {\r
10157                 printf( "HeapLogClass_addWatch: Error of IndexNum (%d)\n", in_IndexNum );\r
10158                 return;\r
10159         }\r
10160 \r
10161         if ( in_IsPrintf ) {\r
10162                 printf( "<HeapLogClass_addWatch  index=\"%d\"  allocated_id=\"%d\"  offset=\"0x%04X\"/>\n",\r
10163                         in_IndexNum,  in_AllocatedID,  in_Offset );\r
10164         }\r
10165         watch->AllocatedID = in_AllocatedID;\r
10166         watch->Offset = in_Offset;\r
10167         watch->BreakValue = in_BreakValue;\r
10168         watch->IsPrintf = in_IsPrintf;\r
10169         watch->IsEnabled = true;\r
10170 }\r
10171 \r
10172 \r
10173 /***********************************************************************\r
10174   <<< [HeapLogClass_watch] >>> \r
10175 ************************************************************************/\r
10176 void  HeapLogClass_watch( int  in_IndexNum )\r
10177 {\r
10178         HeapLogWatchClass*  watch = &g_HeapLogWatch[ in_IndexNum ];\r
10179 \r
10180         uint32_t  value;\r
10181 \r
10182 \r
10183         if ( in_IndexNum >= _countof( g_HeapLogWatch ) ) {\r
10184                 printf( "HeapLogClass_addWatch: Error of IndexNum (%d)\n", in_IndexNum );\r
10185                 return;\r
10186         }\r
10187 \r
10188         if ( watch->IsEnabled  &&  g_HeapLog.Count > watch->AllocatedID ) {\r
10189                 const void*  pointer = g_HeapLog.Addresses[ watch->AllocatedID ];\r
10190 \r
10191                 PointerType_plus( &pointer,  watch->Offset );\r
10192                 value = *(uint32_t*) pointer;\r
10193 \r
10194                 if ( watch->IsPrintf ) {\r
10195                         printf( "<HeapLogClass_watch  index=\"%d\"  value=\"%d\"  value16=\"0x%08X\"/>\n",\r
10196                                 in_IndexNum,  value,  value );\r
10197                 }\r
10198                 if ( value == watch->BreakValue ) { DebugBreakR(); }\r
10199         }\r
10200 \r
10201 }\r
10202 \r
10203 \r
10204 /***********************************************************************\r
10205   <<< [HeapLogClass_getWatchingAddress] >>> \r
10206 ************************************************************************/\r
10207 void*  HeapLogClass_getWatchingAddress( int  in_IndexNum )\r
10208 {\r
10209         HeapLogWatchClass*  watch = &g_HeapLogWatch[ in_IndexNum ];\r
10210         void*  return_value;\r
10211 \r
10212 \r
10213         if ( in_IndexNum >= _countof( g_HeapLogWatch ) ) {\r
10214                 printf( "HeapLogClass_addWatch: Error of IndexNum (%d)\n", in_IndexNum );\r
10215                 return  NULL;\r
10216         }\r
10217 \r
10218 \r
10219         if ( watch->IsEnabled  &&  g_HeapLog.Count > watch->AllocatedID ) {\r
10220                 return_value = g_HeapLog.Addresses[ watch->AllocatedID ];\r
10221                 PointerType_plus( &return_value,  watch->Offset );\r
10222         } else {\r
10223                 return_value = NULL;\r
10224         }\r
10225 \r
10226         return  return_value;\r
10227 }\r
10228 \r
10229 \r
10230 /***********************************************************************\r
10231   <<< [HeapLogClass_finalize] >>> \r
10232 ************************************************************************/\r
10233 void  HeapLogClass_finalize()\r
10234 {\r
10235         if ( g_HeapLog.Addresses != NULL ) {\r
10236                 free( g_HeapLog.Addresses );\r
10237                 g_HeapLog.Addresses = NULL;\r
10238         }\r
10239         if ( g_HeapLog.Sizes != NULL ) {\r
10240                 free( g_HeapLog.Sizes );\r
10241                 g_HeapLog.Sizes = NULL;\r
10242         }\r
10243         g_HeapLog.Count = 0;\r
10244         g_HeapLog.CountMax = 0;\r
10245 }\r
10246 \r
10247 \r
10248  \r
10249 /***********************************************************************\r
10250   <<< [TestableDebugBreak] >>> \r
10251 ************************************************************************/\r
10252 typedef struct _TestableDebugBreakClass  TestableDebugBreakClass;\r
10253 struct _TestableDebugBreakClass {\r
10254         bool              IsDisableTestableDebugBreak;\r
10255         volatile int      DebugBreakCount;\r
10256         CRITICAL_SECTION  Critical;\r
10257         SingletonInitializerClass  Initializer;\r
10258 };\r
10259 static TestableDebugBreakClass  gs_TestableDebugBreak = { false, 0 };\r
10260 \r
10261 \r
10262 /*[SetTestableDebugBreak]*/\r
10263 void  SetTestableDebugBreak( bool IsEnableBreak )\r
10264 {\r
10265         TestableDebugBreakClass*  self = &gs_TestableDebugBreak;\r
10266         self->IsDisableTestableDebugBreak = ! IsEnableBreak;\r
10267 }\r
10268 \r
10269 /*[TestableDebugBreak_Sub]*/\r
10270 int  TestableDebugBreak_Sub()\r
10271 {\r
10272         TestableDebugBreakClass*  self = &gs_TestableDebugBreak;\r
10273 \r
10274         if ( ! SingletonInitializerClass_isInitialized( &self->Initializer ) ) {\r
10275                 if ( SingletonInitializerClass_isFirst( &self->Initializer ) ) {\r
10276 \r
10277                         InitializeCriticalSection( &self->Critical );\r
10278 \r
10279                         SingletonInitializerClass_onFinishedInitialize( &self->Initializer, 0 );\r
10280                 }\r
10281         }\r
10282 \r
10283         EnterCriticalSection( &self->Critical );\r
10284         self->DebugBreakCount += 1;\r
10285         LeaveCriticalSection( &self->Critical );\r
10286 \r
10287         return  ! self->IsDisableTestableDebugBreak;\r
10288 }\r
10289 \r
10290 /*[GetDebugBreakCount]*/\r
10291 int  GetDebugBreakCount()\r
10292 {\r
10293         TestableDebugBreakClass*  self = &gs_TestableDebugBreak;\r
10294         return  self->DebugBreakCount;\r
10295 }\r
10296 \r
10297 \r
10298  \r
10299 /*=================================================================*/\r
10300 /* <<< [SetX/SetX.c] >>> */ \r
10301 /*=================================================================*/\r
10302  \r
10303 /***********************************************************************\r
10304   <<< [Set2_init] >>> \r
10305 ************************************************************************/\r
10306 errnum_t  Set2_init( Set2* m, int FirstSize )\r
10307 {\r
10308         m->First = malloc( FirstSize );\r
10309         if ( m->First == NULL )  return  E_FEW_MEMORY;\r
10310         m->Next = m->First;\r
10311         m->Over = (char*)m->First + FirstSize;\r
10312 \r
10313         #ifdef _DEBUG\r
10314         m->PointerOfDebugArray = NULL;\r
10315         #endif\r
10316 \r
10317         return  0;\r
10318 }\r
10319  \r
10320 /***********************************************************************\r
10321   <<< [Set2_finish] >>> \r
10322 ************************************************************************/\r
10323 errnum_t  Set2_finish( Set2* m, errnum_t e )\r
10324 {\r
10325         if ( m->First != NULL )  { free( m->First );  m->First = NULL; }\r
10326         return  e;\r
10327 }\r
10328 \r
10329  \r
10330 /***********************************************************************\r
10331   <<< [Set2_ref_imp] >>> \r
10332 ************************************************************************/\r
10333 errnum_t  Set2_ref_imp( Set2* m, int iElem, void* out_pElem, size_t ElemSize )\r
10334 {\r
10335         int    e;\r
10336         char*  p;\r
10337 \r
10338         IF( iElem < 0 ) goto err_ns;\r
10339         p = (char*) m->First + ( (unsigned)iElem * ElemSize );\r
10340         IF( p >= (char*)m->Next ) goto err_ns;\r
10341         *(char**)out_pElem = p;\r
10342 \r
10343         e=0;\r
10344 fin:\r
10345         return  e;\r
10346 \r
10347 err_ns:  e = E_NOT_FOUND_SYMBOL;  goto fin;\r
10348 }\r
10349 \r
10350 \r
10351  \r
10352 /***********************************************************************\r
10353   <<< [Set2_getIterator] >>> \r
10354 ************************************************************************/\r
10355 errnum_t  Set2_getIterator( Set2* self, Set2_IteratorClass* out_Iterator, int ElementSize )\r
10356 {\r
10357         out_Iterator->Parent = self;\r
10358         out_Iterator->ElementSize = ElementSize;\r
10359         out_Iterator->Current = (uint8_t*) self->First - ElementSize;\r
10360         return  0;\r
10361 }\r
10362 \r
10363 \r
10364  \r
10365 /***********************************************************************\r
10366   <<< [Set2_getDescendingIterator] >>> \r
10367 ************************************************************************/\r
10368 errnum_t  Set2_getDescendingIterator( Set2* self, Set2_IteratorClass* out_Iterator, int ElementSize )\r
10369 {\r
10370         out_Iterator->Parent = self;\r
10371         out_Iterator->ElementSize = ElementSize;\r
10372         out_Iterator->Current = (uint8_t*) self->Next;\r
10373         return  0;\r
10374 }\r
10375 \r
10376 \r
10377  \r
10378 /***********************************************************************\r
10379   <<< [Set2_IteratorClass_getNext] >>> \r
10380 ************************************************************************/\r
10381 void*  Set2_IteratorClass_getNext( Set2_IteratorClass* self )\r
10382 {\r
10383         uint8_t*  next = self->Current + self->ElementSize;\r
10384 \r
10385         if ( next >= (uint8_t*) self->Parent->Next ) {\r
10386                 return  NULL;\r
10387         } else {\r
10388                 self->Current = next;\r
10389                 return  next;\r
10390         }\r
10391 }\r
10392 \r
10393 \r
10394  \r
10395 /***********************************************************************\r
10396   <<< [Set2_IteratorClass_getPrevious] >>> \r
10397 ************************************************************************/\r
10398 void*  Set2_IteratorClass_getPrevious( Set2_IteratorClass* self )\r
10399 {\r
10400         uint8_t*  previous = self->Current - self->ElementSize;\r
10401 \r
10402         if ( previous < (uint8_t*) self->Parent->First ) {\r
10403                 return  NULL;\r
10404         } else {\r
10405                 self->Current = previous;\r
10406                 return  previous;\r
10407         }\r
10408 }\r
10409 \r
10410 \r
10411  \r
10412 /***********************************************************************\r
10413   <<< [Set2_alloc_imp] >>> \r
10414 ************************************************************************/\r
10415 errnum_t  Set2_alloc_imp( Set2* m, void* pp, size_t size )\r
10416 {\r
10417         errnum_t  e;\r
10418 \r
10419         e= Set2_expandIfOverByAddr( m, (char*) m->Next + size ); IF(e)goto fin;\r
10420         *(void**)pp = m->Next;\r
10421         m->Next = (char*) m->Next + size;\r
10422 \r
10423         DISCARD_BYTES( *(void**)pp, size );\r
10424 \r
10425         e=0;\r
10426 fin:\r
10427         return  e;\r
10428 }\r
10429 \r
10430 \r
10431 /***********************************************************************\r
10432   <<< [Set2_allocMulti_sub] >>> \r
10433 ************************************************************************/\r
10434 errnum_t  Set2_allocMulti_sub( Set2* m, void* out_pElem, size_t ElemsSize )\r
10435 {\r
10436         errnum_t  e;\r
10437         char*     p;\r
10438 \r
10439         e= Set2_expandIfOverByAddr( m, (char*) m->Next + ElemsSize ); IF(e)goto fin;\r
10440         p = (char*) m->Next;\r
10441         m->Next = p + ElemsSize;\r
10442         *(char**)out_pElem = p;\r
10443 \r
10444         e=0;\r
10445 fin:\r
10446         return  e;\r
10447 }\r
10448 \r
10449 \r
10450  \r
10451 /***********************************************************************\r
10452   <<< [Set2_expandIfOverByAddr_imp] >>> \r
10453 ************************************************************************/\r
10454 errnum_t  Set2_expandIfOverByAddr_imp( Set2* m, void* OverAddrBasedOnNowFirst )\r
10455 {\r
10456         errnum_t  e;\r
10457         void*     new_first;\r
10458         unsigned  offset_of_over;\r
10459         unsigned  offset_of_next;\r
10460 \r
10461         if ( OverAddrBasedOnNowFirst <= m->Over ) { e=E_OTHERS; goto fin; }\r
10462 \r
10463         offset_of_next = (unsigned)( (char*)OverAddrBasedOnNowFirst - (char*)m->First );\r
10464         offset_of_over = (unsigned)( ( (char*)m->Over - (char*)m->First ) ) * 2;\r
10465         IF_D( offset_of_next >= 0x80000000 ) { e=E_OTHERS; goto fin; }\r
10466         if ( offset_of_over == 0 ) { offset_of_over = 0x100; }\r
10467         while ( offset_of_over < offset_of_next ) { offset_of_over *= 2; }\r
10468         IF( offset_of_over >= 0x10000000 ) { e=E_OTHERS; goto fin; }\r
10469 \r
10470         new_first = realloc( m->First, offset_of_over * 2 );\r
10471                 IF( new_first == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
10472 \r
10473         m->Next = (char*) new_first + ( (char*)m->Next - (char*)m->First );\r
10474         m->Over = (char*) new_first + offset_of_over * 2;\r
10475         m->First = new_first;\r
10476 \r
10477         #ifdef _DEBUG\r
10478         if ( m->PointerOfDebugArray != NULL )\r
10479                 { *m->PointerOfDebugArray = m->First; }\r
10480         #endif\r
10481 \r
10482         e=0;\r
10483 fin:\r
10484         return  e;\r
10485 }\r
10486 \r
10487 \r
10488  \r
10489 /***********************************************************************\r
10490   <<< [Set2_free_imp] >>> \r
10491 ************************************************************************/\r
10492 errnum_t  Set2_free_imp( Set2* self,  void* in_PointerOfPointer,  size_t  in_Size_ofElement,  errnum_t  e )\r
10493 {\r
10494         void*  element;\r
10495 \r
10496         element = *(void**) in_PointerOfPointer;\r
10497 \r
10498         if ( element != NULL ) {\r
10499                 if ( element != ( (byte_t*) self->Next - in_Size_ofElement ) ) {\r
10500                         if ( e == 0 ) { e=E_OTHERS; }\r
10501                 }\r
10502                 else {\r
10503                         #ifndef NDEBUG\r
10504                                 memset( element, 0xFE, in_Size_ofElement );\r
10505                         #endif\r
10506 \r
10507                         self->Next = element;\r
10508 \r
10509                         *(void**) in_PointerOfPointer = NULL;\r
10510                 }\r
10511         }\r
10512         return  e;\r
10513 }\r
10514 \r
10515 \r
10516  \r
10517 /***********************************************************************\r
10518   <<< [Set2_separate] >>> \r
10519 ************************************************************************/\r
10520 errnum_t  Set2_separate( Set2* m, int NextSize, void** allocate_Array )\r
10521 {\r
10522         errnum_t  e;\r
10523         void*     p = m->First;\r
10524 \r
10525         if ( NextSize == 0 ) {\r
10526                 m->First = NULL;\r
10527                 m->Next  = NULL;\r
10528                 m->Over  = NULL;\r
10529         }\r
10530         else {\r
10531                 e= Set2_init( m, NextSize ); IF(e)goto fin;\r
10532         }\r
10533         *allocate_Array = p;\r
10534 \r
10535         e=0;\r
10536 fin:\r
10537         return  e;\r
10538 }\r
10539 \r
10540 \r
10541  \r
10542 /***********************************************************************\r
10543   <<< [Set2_pop_imp] >>> \r
10544 ************************************************************************/\r
10545 errnum_t  Set2_pop_imp( Set2* m, void* pp, size_t size )\r
10546 {\r
10547         errnum_t  e;\r
10548         void*     p;\r
10549 \r
10550         p = (char*) m->Next - size;\r
10551 \r
10552         IF ( p < m->First ) { e=E_OTHERS; goto fin; }\r
10553 \r
10554         m->Next = p;\r
10555         *(void**)pp = p;\r
10556 \r
10557         e=0;\r
10558 fin:\r
10559         return  e;\r
10560 }\r
10561 \r
10562 \r
10563  \r
10564 /***********************************************************************\r
10565   <<< [Set2_setDebug] >>> \r
10566 ************************************************************************/\r
10567 #ifdef _DEBUG\r
10568 void  Set2_setDebug( Set2* m, void* PointerOfDebugArray )\r
10569 {\r
10570         m->PointerOfDebugArray = (void**) PointerOfDebugArray;\r
10571         *m->PointerOfDebugArray = m->First;\r
10572 }\r
10573 #endif\r
10574 \r
10575 \r
10576  \r
10577 /***********************************************************************\r
10578   <<< [Set2a_init] >>> \r
10579 ************************************************************************/\r
10580 int  Set2a_init( Set2a* m, void* ArrInStack, size_t ArrInStack_Size )\r
10581 {\r
10582         int  e;\r
10583 \r
10584         /* "m->First" is initialized in "Set2a_initConst" */\r
10585 \r
10586         m->Next = m->First;\r
10587         m->Over = (char*)m->First + ArrInStack_Size;\r
10588 \r
10589         ASSERT_D( m->First == ArrInStack,  e=E_OTHERS; goto fin );\r
10590 \r
10591         #ifdef _DEBUG\r
10592                 m->PointerOfDebugArray = NULL;\r
10593         #endif\r
10594 \r
10595         e=0;\r
10596 #ifdef _DEBUG\r
10597 fin:\r
10598 #else\r
10599         UNREFERENCED_VARIABLE( ArrInStack );\r
10600 #endif\r
10601         return  e;\r
10602 }\r
10603 \r
10604 \r
10605  \r
10606 /***********************************************************************\r
10607   <<< [Set2a_alloc_imp] >>> \r
10608 ************************************************************************/\r
10609 int  Set2a_alloc_imp( Set2a* m, void* ArrInStack, void* out_Pointer, size_t ElemSize )\r
10610 {\r
10611         int  e;\r
10612 \r
10613         e= Set2a_expandIfOverByAddr_imp( m, ArrInStack, (char*)m->Next + ElemSize ); IF(e)goto fin;\r
10614         *(void**)out_Pointer = m->Next;\r
10615         m->Next = (char*) m->Next + ElemSize;\r
10616 \r
10617         e=0;\r
10618 fin:\r
10619         return  e;\r
10620 }\r
10621 \r
10622 \r
10623 \r
10624  \r
10625 /***********************************************************************\r
10626   <<< [Set2a_expandIfOverByAddr_imp] >>> \r
10627 ************************************************************************/\r
10628 int  Set2a_expandIfOverByAddr_imp( Set2a* m, void* ArrInStack, void* OverAddrBasedOnNowFirst )\r
10629 {\r
10630         void*  new_memory;\r
10631         unsigned  ofs;\r
10632 \r
10633         if ( m->First == ArrInStack ) {\r
10634                 ofs = (char*)m->Over - (char*)m->First;\r
10635                 new_memory = malloc( ofs * 2 );\r
10636                 IF( new_memory == NULL ) return  E_FEW_MEMORY;\r
10637 \r
10638                 memcpy( new_memory, m->First, ofs * 2 );\r
10639 \r
10640                 m->First = new_memory;\r
10641                 m->Over  = (char*)new_memory + ofs * 2;\r
10642                 m->Next  = (char*)new_memory + ofs;\r
10643                 return  0;\r
10644         }\r
10645         else {\r
10646                 return  Set2_expandIfOverByAddr_imp( (Set2*) m, OverAddrBasedOnNowFirst );\r
10647         }\r
10648 }\r
10649 \r
10650 \r
10651  \r
10652 /*-------------------------------------------------------------------------*/\r
10653 /* <<<< ### (Set4) Class >>>> */ \r
10654 /*-------------------------------------------------------------------------*/\r
10655 \r
10656 \r
10657  \r
10658 /****************************************************************\r
10659   <<< [Set4_init_imp] >>> \r
10660 *****************************************************************/\r
10661 errnum_t  Set4_init_imp( Set4* self,  size_t in_ElementSize,  size_t in_FirstHeapSize )\r
10662 {\r
10663         int  element_count;\r
10664 \r
10665         self->FirstBlock = NULL;\r
10666         self->CurrentBlockFirst = NULL;\r
10667         self->u.NextBlock = &self->FirstBlock;\r
10668         self->CurrentBlockNext = self->u.CurrentBlockOver;\r
10669         element_count = ( in_FirstHeapSize - sizeof(void*) ) / in_ElementSize;\r
10670         self->HeapSize = element_count * in_ElementSize + sizeof(void*);\r
10671         self->ElementSize = in_ElementSize;\r
10672 \r
10673         return  0;\r
10674 }\r
10675 \r
10676 \r
10677  \r
10678 /****************************************************************\r
10679   <<< [Set4_finish2_imp] >>> \r
10680 *****************************************************************/\r
10681 errnum_t  Set4_finish2_imp( Set4* self,  errnum_t  e,  size_t in_ElementSize,  FinalizeFuncType  in_Type_Finalize )\r
10682 {\r
10683         Set4Iter  p;\r
10684 \r
10685         ASSERT_D( self->ElementSize == in_ElementSize,  e= MergeError( e, E_OTHERS ); goto fin );\r
10686 \r
10687         for ( Set4_forEach_imp( self, &p, in_ElementSize ) ) {\r
10688                 e= in_Type_Finalize( p.p, e );\r
10689         }\r
10690 \r
10691 #ifndef NDEBUG\r
10692 fin:\r
10693 #endif\r
10694         return  e;\r
10695 }\r
10696 \r
10697 \r
10698  \r
10699 /****************************************************************\r
10700   <<< [Set4_finish2_imp2] >>> \r
10701 *****************************************************************/\r
10702 errnum_t  Set4_finish2_imp2( Set4* self )\r
10703 {\r
10704         byte_t*  p;\r
10705         byte_t*  p2;\r
10706 \r
10707         p = self->FirstBlock;\r
10708         while ( p != NULL ) {\r
10709                 p2 = *(void**)( p + self->HeapSize - sizeof(void*) );\r
10710                 free( p );\r
10711                 p = p2;\r
10712         }\r
10713 \r
10714         return  0;\r
10715 }\r
10716 \r
10717 \r
10718  \r
10719 /****************************************************************\r
10720   <<< [Set4_alloc_imp] >>> \r
10721 *****************************************************************/\r
10722 errnum_t  Set4_alloc_imp( Set4* self,  void* out_ElementPointer,  size_t  in_ElementSize )\r
10723 {\r
10724         errnum_t  e;\r
10725         byte_t*   new_block;\r
10726         byte_t*   element;\r
10727 \r
10728         ASSERT_D( in_ElementSize == self->ElementSize,  e=E_OTHERS; goto fin );\r
10729 \r
10730         /* Add new element */\r
10731         if ( self->CurrentBlockNext == self->u.CurrentBlockOver ) {\r
10732                 new_block = (byte_t*) malloc( self->HeapSize );\r
10733                 IF ( new_block == NULL ) { e=E_FEW_MEMORY; goto fin; }\r
10734                 element = new_block;\r
10735 \r
10736                 *self->u.NextBlock = new_block;\r
10737                 self->CurrentBlockNext = new_block + in_ElementSize;\r
10738 \r
10739                 self->CurrentBlockFirst = new_block;\r
10740                 self->u.CurrentBlockOver = new_block + self->HeapSize - sizeof(void*);\r
10741                 *self->u.NextBlock = NULL;\r
10742         }\r
10743 \r
10744         /* Add existed element */\r
10745         else {\r
10746                 ASSERT_D( self->CurrentBlockNext < self->u.CurrentBlockOver,  e=E_OTHERS; goto fin );\r
10747                 element = self->CurrentBlockNext;\r
10748                 self->CurrentBlockNext += in_ElementSize;\r
10749         }\r
10750 \r
10751         *(void**) out_ElementPointer = element;\r
10752 \r
10753         e=0;\r
10754 fin:\r
10755         return  e;\r
10756 }\r
10757 \r
10758 \r
10759  \r
10760 /****************************************************************\r
10761   <<< [Set4_free_imp] >>> \r
10762 *****************************************************************/\r
10763 errnum_t  Set4_free_imp( Set4* self,  void* in_out_ElementPointer,  size_t in_ElementSize,  errnum_t e0 )\r
10764 {\r
10765         errnum_t  e;\r
10766         void*     element = *(void**) in_out_ElementPointer;\r
10767 \r
10768         ASSERT_D( in_ElementSize == self->ElementSize,  e=E_OTHERS; goto fin );\r
10769 \r
10770         if ( element != NULL ) {\r
10771                 if ( self->CurrentBlockNext == self->CurrentBlockFirst ) {\r
10772                         byte_t*  block;\r
10773                         byte_t*  previous_block = NULL;\r
10774                         byte_t*  previous_element;\r
10775 \r
10776                         for (\r
10777                                 block = self->FirstBlock;\r
10778                                 block != NULL;\r
10779                                 block = *(byte_t**)( block + self->HeapSize - sizeof(void*) ) )\r
10780                         {\r
10781                                 if ( block == self->CurrentBlockFirst )\r
10782                                         { break; }\r
10783 \r
10784                                 previous_block = block;\r
10785                         }\r
10786                         ASSERT_R( previous_block != NULL,  e=E_OTHERS; goto fin );\r
10787 \r
10788                         previous_element = previous_block + self->HeapSize - sizeof(void*) - in_ElementSize;\r
10789                         ASSERT_R( element == previous_element,  e=E_ACCESS_DENIED; goto fin );\r
10790 \r
10791                         free( block );\r
10792                         self->CurrentBlockFirst = previous_block;\r
10793                         self->CurrentBlockNext = previous_element;\r
10794                         self->u.CurrentBlockOver = previous_element + in_ElementSize;\r
10795                         *self->u.NextBlock = NULL;\r
10796                 }\r
10797                 else {\r
10798                         byte_t*  previous_element = self->CurrentBlockNext - in_ElementSize;\r
10799 \r
10800                         ASSERT_D( element == previous_element,  e=E_ACCESS_DENIED; goto fin );\r
10801 \r
10802                         self->CurrentBlockNext = previous_element;\r
10803                 }\r
10804 \r
10805                 *(void**) in_out_ElementPointer = NULL;\r
10806         }\r
10807 \r
10808         e=0;\r
10809 fin:\r
10810         if ( e0 == 0 )\r
10811                 { e0 = e; }\r
10812         return  e0;\r
10813 }\r
10814 \r
10815 \r
10816  \r
10817 /****************************************************************\r
10818   <<< [Set4_ref_imp] >>> \r
10819 *****************************************************************/\r
10820 void*  Set4_ref_imp( Set4* self, int i, int size )\r
10821 {\r
10822         byte_t*  p = self->FirstBlock;\r
10823         size_t   offset = i * size;\r
10824         size_t   offset_over = self->HeapSize - sizeof(void*);\r
10825 \r
10826         if ( i < 0 )  { return  NULL; }\r
10827 \r
10828         if ( p == NULL )  { return  NULL; }\r
10829         while ( offset >= offset_over ) {\r
10830                 p = *(void**)( (char*)p + offset_over );\r
10831                 if ( p == NULL )  { return  NULL; }\r
10832                 offset -= offset_over;\r
10833         }\r
10834 \r
10835         p += offset;\r
10836         if ( p >= self->CurrentBlockNext )  { return  NULL; }\r
10837 \r
10838         return  p;\r
10839 }\r
10840 \r
10841 \r
10842  \r
10843 /****************************************************************\r
10844   <<< [Set4_getCount_imp] >>> \r
10845 *****************************************************************/\r
10846 int  Set4_getCount_imp( Set4* self, int size )\r
10847 {\r
10848         void*  p = self->FirstBlock;\r
10849         void*  p2 = NULL;\r
10850         int    offset = 0;\r
10851         int    offset_over = self->HeapSize - sizeof(void*);\r
10852 \r
10853         if ( p == NULL )  { return  0; }\r
10854 \r
10855         for (;;) {\r
10856                 p2 = p;\r
10857                 p = *(void**)( (char*)p + offset_over );\r
10858                 if ( p == NULL )  break;\r
10859                 offset += offset_over;\r
10860         }\r
10861 \r
10862         offset += (int)( (char*)self->CurrentBlockNext - (char*)p2 );\r
10863 \r
10864         return  offset / size;\r
10865 }\r
10866 \r
10867 \r
10868  \r
10869 /****************************************************************\r
10870   <<< [Set4_forEach_imp2] >>> \r
10871 *****************************************************************/\r
10872 void  Set4_forEach_imp2( Set4* self, Set4Iter* p, int size )\r
10873 {\r
10874         if ( p->p == NULL ) {  /* first */\r
10875                 if ( self->FirstBlock == NULL )  return;  /* elem count = 0 */\r
10876                 p->Over = &self->FirstBlock;\r
10877         }\r
10878         else {  /* The next of array */\r
10879                 p->p = (char*)p->p + size;\r
10880                 if ( p->p < p->Over )  return;\r
10881         }\r
10882 \r
10883         /* The last element */\r
10884         if ( p->p == self->CurrentBlockNext )  { p->p = NULL;  return; }\r
10885 \r
10886         /* The next element */\r
10887         p->p = *(void**) p->Over;\r
10888         p->Over = (char*)p->p + self->HeapSize - sizeof(void*);\r
10889         if ( *(void**)p->Over == NULL )  p->Over = self->CurrentBlockNext;\r
10890 }\r
10891 \r
10892 \r
10893  \r
10894 /***********************************************************************\r
10895   <<< (ListClass) >>> \r
10896 ************************************************************************/\r
10897 \r
10898 /*[ListClass_initConst]*/\r
10899 void  ListClass_initConst( ListClass* self )\r
10900 {\r
10901         self->Terminator.Data     = NULL;\r
10902         self->Terminator.List     = self;\r
10903         self->Terminator.Next     = &self->Terminator;\r
10904         self->Terminator.Previous = &self->Terminator;\r
10905         self->Count               = 0;\r
10906 }\r
10907 \r
10908 \r
10909 /*[ListClass_addAtIndex]*/\r
10910 errnum_t  ListClass_addAtIndex( ListClass* self, int Index, ListElementClass* Element )\r
10911 {\r
10912         errnum_t           e;\r
10913         ListElementClass*  target;\r
10914 \r
10915         if ( Index == self->Count ) {\r
10916                 e= ListClass_addLast( self, Element ); IF(e){goto fin;}\r
10917         }\r
10918         else {\r
10919                 e= ListClass_get( self, Index, &target ); IF(e){goto fin;}\r
10920                 e= ListClass_addAt_Sub( Element, target ); IF(e){goto fin;}\r
10921         }\r
10922 \r
10923         e=0;\r
10924 fin:\r
10925         return  e;\r
10926 }\r
10927 \r
10928 \r
10929 /*[ListClass_addAt_Sub]*/\r
10930 errnum_t  ListClass_addAt_Sub( ListElementClass* AddingElement, ListElementClass* Target )\r
10931 {\r
10932         errnum_t           e;\r
10933         ListElementClass*  target_previous = Target->Previous;\r
10934         ListClass*         self = Target->List;\r
10935 \r
10936         ASSERT_R( AddingElement->List == NULL,  e=E_ACCESS_DENIED; goto fin );\r
10937 \r
10938         AddingElement->Next = Target;\r
10939         AddingElement->Previous = target_previous;\r
10940         target_previous->Next = AddingElement;\r
10941         Target->Previous = AddingElement;\r
10942         AddingElement->List = self;\r
10943         self->Count += 1;\r
10944 \r
10945         e=0;\r
10946 fin:\r
10947         return  e;\r
10948 }\r
10949 \r
10950 \r
10951 /*[ListClass_get]*/\r
10952 errnum_t  ListClass_get( ListClass* self, int Index, ListElementClass** out_Element )\r
10953 {\r
10954         errnum_t           e;\r
10955         ListElementClass*  element = self->Terminator.Next;\r
10956 \r
10957         ASSERT_R( Index >= 0  &&  Index < self->Count,  e=E_NOT_FOUND_SYMBOL; goto fin );\r
10958 \r
10959         while ( Index != 0 ) {\r
10960                 element = element->Next;\r
10961                 Index -= 1;\r
10962         }\r
10963 \r
10964         *out_Element = element;\r
10965 \r
10966         e=0;\r
10967 fin:\r
10968         return  e;\r
10969 }\r
10970 \r
10971 \r
10972 /*[ListClass_set]*/\r
10973 errnum_t  ListClass_set( ListClass* self, int Index, ListElementClass* Element )\r
10974 {\r
10975         errnum_t           e;\r
10976         ListElementClass*  target;\r
10977 \r
10978         ASSERT_R( Element->List == NULL,  e=E_ACCESS_DENIED; goto fin );\r
10979 \r
10980         e= ListClass_get( self, Index, &target ); IF(e){goto fin;}\r
10981         e= ListClass_replace( self, target, Element ); IF(e){goto fin;}\r
10982 \r
10983         e=0;\r
10984 fin:\r
10985         return  e;\r
10986 }\r
10987 \r
10988 \r
10989 /*[ListClass_replace]*/\r
10990 errnum_t  ListClass_replace( ListClass* self, ListElementClass* RemovingElement,\r
10991         ListElementClass* AddingElement )\r
10992 {\r
10993         errnum_t  e;\r
10994 \r
10995         ASSERT_R( RemovingElement->List == self,  e=E_NOT_FOUND_SYMBOL; goto fin );\r
10996         ASSERT_R( AddingElement->List == NULL,  e=E_ACCESS_DENIED; goto fin );\r
10997         ASSERT_R( RemovingElement != &RemovingElement->List->Terminator,\r
10998                 e=E_NOT_FOUND_SYMBOL; goto fin );\r
10999 \r
11000         RemovingElement->Next->Previous  = AddingElement;\r
11001         RemovingElement->Previous->Next  = AddingElement;\r
11002         AddingElement->Next     = RemovingElement->Next;\r
11003         AddingElement->Previous = RemovingElement->Previous;\r
11004 \r
11005         AddingElement->List = self;\r
11006 \r
11007         RemovingElement->List  = NULL;\r
11008         #ifndef NDEBUG\r
11009                 RemovingElement->Next     = NULL;\r
11010                 RemovingElement->Previous = NULL;\r
11011         #endif\r
11012 \r
11013         e=0;\r
11014 fin:\r
11015         return  e;\r
11016 }\r
11017 \r
11018 \r
11019 /*[ListClass_getIndexOfData]*/\r
11020 int  ListClass_getIndexOfData( ListClass* self, void* Data )\r
11021 {\r
11022         int                index;\r
11023         ListElementClass*  element    =  self->Terminator.Next;\r
11024         ListElementClass*  tarminator = &self->Terminator;\r
11025 \r
11026         for ( index = 0; ; index += 1 ) {\r
11027                 if ( element == tarminator )\r
11028                         { return  INVALID_ARRAY_INDEX; }\r
11029 \r
11030                 if ( element->Data == Data )\r
11031                         { return  index; }\r
11032 \r
11033                 element = element->Next;\r
11034         }\r
11035 }\r
11036 \r
11037 \r
11038 /*[ListClass_getIndexOf]*/\r
11039 int  ListClass_getIndexOf( ListClass* self, ListElementClass* Element )\r
11040 {\r
11041         int                index;\r
11042         ListElementClass*  elem       =  self->Terminator.Next;\r
11043         ListElementClass*  tarminator = &self->Terminator;\r
11044 \r
11045         for ( index = 0; ; index += 1 ) {\r
11046                 if ( elem == Element )\r
11047                         { return  index; }\r
11048 \r
11049                 if ( elem == tarminator )\r
11050                         { return  INVALID_ARRAY_INDEX; }\r
11051 \r
11052                 elem = elem->Next;\r
11053         }\r
11054 }\r
11055 \r
11056 \r
11057 /*[ListClass_getLastIndexOfData]*/\r
11058 int  ListClass_getLastIndexOfData( ListClass* self, void* Data )\r
11059 {\r
11060         int                index;\r
11061         ListElementClass*  element    =  self->Terminator.Previous;\r
11062         ListElementClass*  tarminator = &self->Terminator;\r
11063 \r
11064         for ( index = self->Count - 1; ; index -= 1 ) {\r
11065                 if ( element == tarminator )\r
11066                         { return  INVALID_ARRAY_INDEX; }\r
11067 \r
11068                 if ( element->Data == Data )\r
11069                         { return  index; }\r
11070 \r
11071                 element = element->Previous;\r
11072         }\r
11073 }\r
11074 \r
11075 \r
11076 /*[ListClass_getArray]*/\r
11077 errnum_t  ListClass_getArray( ListClass* self, void* DataArray, size_t DataArraySize )\r
11078 {\r
11079         errnum_t           e;\r
11080         ListIteratorClass  iterator;\r
11081         void*              data;\r
11082         void**             data_pointer;\r
11083 \r
11084         ASSERT_R( DataArraySize >= self->Count * sizeof(void*),  e=E_FEW_ARRAY; goto fin );\r
11085 \r
11086         e= ListClass_getListIterator( self, &iterator ); IF(e){goto fin;}\r
11087         for ( data_pointer = (void**) DataArray;  ;  data_pointer += 1 ) {\r
11088                 data = ListIteratorClass_getNext( &iterator );\r
11089                         if ( data == NULL ) { break; }\r
11090 \r
11091                 *data_pointer = data;\r
11092         }\r
11093 \r
11094         e=0;\r
11095 fin:\r
11096         return  e;\r
11097 }\r
11098 \r
11099 \r
11100 /*[ListClass_removeByIndex]*/\r
11101 errnum_t  ListClass_removeByIndex( ListClass* self, int Index )\r
11102 {\r
11103         errnum_t           e;\r
11104         ListElementClass*  target;\r
11105 \r
11106         e= ListClass_get( self, Index, &target ); IF(e){goto fin;}\r
11107         e= ListClass_remove( self, target ); IF(e){goto fin;}\r
11108 \r
11109         e=0;\r
11110 fin:\r
11111         return  e;\r
11112 }\r
11113 \r
11114 \r
11115 /*[ListClass_remove]*/\r
11116 errnum_t  ListClass_remove( ListClass* self, ListElementClass* Element )\r
11117 {\r
11118         if ( Element->List == self ) {\r
11119                 Element->Previous->Next = Element->Next;\r
11120                 Element->Next->Previous = Element->Previous;\r
11121                 Element->List           = NULL;\r
11122                 #ifndef NDEBUG\r
11123                         Element->Next     = NULL;\r
11124                         Element->Previous = NULL;\r
11125                 #endif\r
11126                 self->Count -= 1;\r
11127         }\r
11128         return  0;\r
11129 }\r
11130 \r
11131 \r
11132 /*[ListClass_clear]*/\r
11133 errnum_t  ListClass_clear( ListClass* self )\r
11134 {\r
11135         ListElementClass*  target = self->Terminator.Next;\r
11136         ListElementClass*  next;\r
11137         ListElementClass*  terminator = &self->Terminator;\r
11138 \r
11139         while ( target != terminator ) {\r
11140                 target->List = NULL;\r
11141 \r
11142                 next = target->Next;\r
11143                 #ifndef NDEBUG\r
11144                         target->Next     = NULL;\r
11145                         target->Previous = NULL;\r
11146                 #endif\r
11147                 target = next;\r
11148         }\r
11149 \r
11150         self->Terminator.Next     = terminator;\r
11151         self->Terminator.Previous = terminator;\r
11152         self->Count = 0;\r
11153 \r
11154         return  0;\r
11155 }\r
11156 \r
11157 \r
11158 /*[ListIteratorClass_getNext]*/\r
11159 void*  ListIteratorClass_getNext( ListIteratorClass* self )\r
11160 {\r
11161         ListElementClass*  next = self->Element->Next;\r
11162 \r
11163         self->Element = next;\r
11164 \r
11165         if ( next == &next->List->Terminator )\r
11166                 { return  NULL; }\r
11167         else\r
11168                 { return  next->Data; }\r
11169 }\r
11170 \r
11171 \r
11172 /*[ListIteratorClass_getPrevious]*/\r
11173 void*  ListIteratorClass_getPrevious( ListIteratorClass* self )\r
11174 {\r
11175         ListElementClass*  previous = self->Element->Previous;\r
11176 \r
11177         self->Element = previous;\r
11178 \r
11179         if ( previous == &previous->List->Terminator )\r
11180                 { return  NULL; }\r
11181         else\r
11182                 { return  previous->Data; }\r
11183 }\r
11184 \r
11185 \r
11186 /*[ListIteratorClass_replace]*/\r
11187 errnum_t  ListIteratorClass_replace( ListIteratorClass* self, ListElementClass* AddingElement )\r
11188 {\r
11189         errnum_t  e;\r
11190         ListElementClass*  removing_element = self->Element;\r
11191 \r
11192         e= ListClass_replace( removing_element->List, removing_element, AddingElement );\r
11193                 IF(e){goto fin;}\r
11194         self->Element = AddingElement;\r
11195 \r
11196         e=0;\r
11197 fin:\r
11198         return  e;\r
11199 }\r
11200 \r
11201 \r
11202 /*[ListIteratorClass_remove]*/\r
11203 errnum_t  ListIteratorClass_remove( ListIteratorClass* self )\r
11204 {\r
11205         errnum_t  e;\r
11206         ListElementClass*  removing_element = self->Element;\r
11207 \r
11208         ASSERT_R( removing_element->List != NULL,  e=E_NOT_FOUND_SYMBOL; goto fin );\r
11209                 /* Already removed */\r
11210         ASSERT_R( removing_element != &removing_element->List->Terminator,\r
11211                 e=E_NOT_FOUND_SYMBOL; goto fin );  /* Over next or previous */\r
11212 \r
11213         self->ModifiedElement.Next     = removing_element->Next;\r
11214         self->ModifiedElement.Previous = removing_element->Previous;\r
11215         self->Element = &self->ModifiedElement;\r
11216 \r
11217         e= ListClass_remove( removing_element->List, removing_element ); IF(e){goto fin;}\r
11218 \r
11219         e=0;\r
11220 fin:\r
11221         return  e;\r
11222 }\r
11223 \r
11224 \r
11225  \r
11226 /***********************************************************************\r
11227   <<< [ListClass_finalizeWithVTable] >>> \r
11228 ************************************************************************/\r
11229 errnum_t  ListClass_finalizeWithVTable( ListClass* self, bool IsFreeElements, errnum_t e )\r
11230 {\r
11231         errnum_t               ee;\r
11232         ListIteratorClass      iterator;\r
11233         ClassID_SuperClass*    element;\r
11234         FinalizerVTableClass*  v_table;\r
11235 \r
11236         ee= ListClass_getListIterator( self, &iterator );\r
11237         IF ( ee ) {\r
11238                 if ( e == 0 ) { e = ee; }\r
11239                 goto fin;\r
11240         }\r
11241 \r
11242         for (;;) {\r
11243                 element = (ClassID_SuperClass*) ListIteratorClass_getNext( &iterator );\r
11244                         if ( element == NULL ) { break; }\r
11245                 ee= ListIteratorClass_remove( &iterator );\r
11246 \r
11247                 /* Call "Finalize" */\r
11248                 v_table = (FinalizerVTableClass*) ClassID_Class_getVTable(\r
11249                         element->ClassID, &g_FinalizerInterface_ID );\r
11250                 IF ( v_table == NULL ) {\r
11251                         if ( e == 0 ) { e=E_OTHERS; }\r
11252                 }\r
11253                 else {\r
11254                         e= v_table->Finalize( element, e );\r
11255                 }\r
11256 \r
11257                 /* Call "HeapMemory_free" */\r
11258                 if ( IsFreeElements ) {\r
11259                         e= HeapMemory_free( &element, e );\r
11260                 }\r
11261         }\r
11262 \r
11263 fin:\r
11264         return  e;\r
11265 }\r
11266 \r
11267 \r
11268  \r
11269 /***********************************************************************\r
11270   <<< [ListClass_printXML] >>> \r
11271 ************************************************************************/\r
11272 errnum_t  ListClass_printXML( ListClass* self, FILE* OutputStream )\r
11273 {\r
11274         errnum_t               e;\r
11275         ListIteratorClass      iterator;\r
11276         ClassID_SuperClass*    element;\r
11277         PrintXML_VTableClass*  v_table;\r
11278 \r
11279         e= ListClass_getListIterator( self, &iterator ); IF(e){goto fin;}\r
11280         for (;;) {\r
11281                 element = (ClassID_SuperClass*) ListIteratorClass_getNext( &iterator );\r
11282                         if ( element == NULL ) { break; }\r
11283 \r
11284                 /* Call "PrintXML" */\r
11285                 v_table = (PrintXML_VTableClass*) ClassID_Class_getVTable(\r
11286                         element->ClassID, &g_PrintXML_Interface_ID );\r
11287                 if ( v_table == NULL ) {\r
11288                         _ftprintf_s( OutputStream, _T("<UnknownClass error=\"Not found PrintXML_VTable\"/>\n") );\r
11289                 }\r
11290                 else {\r
11291                         e= v_table->PrintXML( element, OutputStream ); IF(e){goto fin;}\r
11292                 }\r
11293         }\r
11294 \r
11295         e=0;\r
11296 fin:\r
11297         return  e;\r
11298 }\r
11299 \r
11300 \r
11301  \r
11302 /***********************************************************************\r
11303   <<< (VariantListClass) >>> \r
11304 ************************************************************************/\r
11305 \r
11306 /*[VariantListClass_initConst]*/\r
11307 void  VariantListClass_initConst( VariantListClass* self )\r
11308 {\r
11309         ListClass_initConst( &self->List );\r
11310 }\r
11311 \r
11312 \r
11313 /*[VariantListClass_finalize]*/\r
11314 errnum_t  VariantListClass_finalize( VariantListClass* self, errnum_t e )\r
11315 {\r
11316         errnum_t               ee;\r
11317         ListIteratorClass      iterator;\r
11318         VariantClass*          variant;\r
11319 \r
11320         ee= ListClass_getListIterator( &self->List, &iterator );\r
11321                 IF (ee) {\r
11322                         if ( e == 0 )  { e = ee; }\r
11323                         goto fin;\r
11324                 }\r
11325 \r
11326         for (;;) {\r
11327                 variant = (VariantClass*) ListIteratorClass_getNext( &iterator );\r
11328                         if ( variant == NULL ) { break; }\r
11329                 ee= ListIteratorClass_remove( &iterator );\r
11330                 if ( ee == 0 ) {\r
11331                         Variant_SuperClass*    object = variant->Object;\r
11332                         FinalizerVTableClass*  v_table;\r
11333 \r
11334                         v_table = ClassID_Class_getVTable( object->ClassID, &g_FinalizerInterface_ID );\r
11335                         if ( v_table != NULL ) {\r
11336                                 e= v_table->Finalize( object, e );\r
11337                         }\r
11338                         e= FreeMemory( &object, e );\r
11339                         e= FreeMemory( &variant, e );\r
11340                 }\r
11341         }\r
11342 \r
11343 fin:\r
11344         return  e;\r
11345 }\r
11346 \r
11347 \r
11348 /*[VariantListClass_createElement]*/\r
11349 errnum_t  VariantListClass_createElement( VariantListClass* self,\r
11350         void* /*<Variant_SuperClass**>*/ out_ElementObject,\r
11351         const ClassID_Class* ClassID,  void* Parameter )\r
11352 {\r
11353         errnum_t             e;\r
11354         VariantClass*        variant = NULL;\r
11355         Variant_SuperClass*  object = NULL;\r
11356         InitializeFuncType   initialize;\r
11357         bool                 is_initialized = false;\r
11358 \r
11359         e= MallocMemory( &variant, sizeof( VariantClass ) );  IF(e){goto fin;}\r
11360         ListElementClass_initConst( &variant->ListElement, variant );\r
11361 \r
11362         e= MallocMemory( &object, ClassID->Size );  IF(e){goto fin;}\r
11363         initialize = ClassID->InitializeFunction;\r
11364         if ( initialize != NULL ) {\r
11365                 e= initialize( object, Parameter );  IF(e){goto fin;}\r
11366         }\r
11367         is_initialized = true;\r
11368 \r
11369         variant->Object = object;\r
11370         object->StaticAddress = variant;\r
11371         e= ListClass_addLast( &self->List, &variant->ListElement ); IF(e){goto fin;}\r
11372 \r
11373         *(Variant_SuperClass**) out_ElementObject = object;\r
11374 \r
11375         e=0;\r
11376 fin:\r
11377         if ( e != 0 ) {\r
11378                 if ( is_initialized ) {\r
11379                         FinalizerVTableClass*  v_table;\r
11380 \r
11381                         v_table = ClassID_Class_getVTable( ClassID, &g_FinalizerInterface_ID );\r
11382                         if ( v_table != NULL ) {\r
11383                                 e= v_table->Finalize( object, e );\r
11384                         }\r
11385                 }\r
11386                 e= FreeMemory( &object, e );\r
11387                 e= FreeMemory( &variant, e );\r
11388         }\r
11389         return  e;\r
11390 }\r
11391 \r
11392 \r
11393 /*[VariantListClass_destroyElement]*/\r
11394 errnum_t  VariantListClass_destroyElement( VariantListClass* self,\r
11395         void* /*<Variant_SuperClass**>*/  in_out_ElementObject,  errnum_t e )\r
11396 {\r
11397         errnum_t               ee;\r
11398         FinalizerVTableClass*  v_table;\r
11399         VariantClass*          variant;\r
11400         Variant_SuperClass*    object = *(Variant_SuperClass**) in_out_ElementObject;\r
11401 \r
11402         if ( object != NULL ) {\r
11403                 variant = object->StaticAddress;\r
11404 \r
11405                 ee= ListClass_remove( &self->List, &variant->ListElement );\r
11406                 UNREFERENCED_VARIABLE( ee );\r
11407 \r
11408                 v_table = ClassID_Class_getVTable( object->ClassID, &g_FinalizerInterface_ID );\r
11409                 if ( v_table != NULL ) {\r
11410                         e= v_table->Finalize( object, e );\r
11411                 }\r
11412                 e= FreeMemory( &object, e );\r
11413                 e= FreeMemory( &variant, e );\r
11414         }\r
11415         *(Variant_SuperClass**) in_out_ElementObject = NULL;\r
11416 \r
11417         return  e;\r
11418 }\r
11419 \r
11420 \r
11421  \r
11422 /***********************************************************************\r
11423   <<< (Variant_SuperClass) >>> \r
11424 ************************************************************************/\r
11425 static const ClassID_Class*  gs_Variant_SuperClass_SuperClassIDs[] = {\r
11426     &g_ClassID_SuperClass_ID, &g_Variant_SuperClass_ID,\r
11427 };\r
11428 \r
11429 /*[g_Variant_SuperClass_ID]*/\r
11430 const ClassID_Class  g_Variant_SuperClass_ID = {\r
11431     "Variant_SuperClass",\r
11432     gs_Variant_SuperClass_SuperClassIDs,\r
11433     _countof( gs_Variant_SuperClass_SuperClassIDs ),\r
11434     sizeof( Variant_SuperClass ),\r
11435     Variant_SuperClass_initialize,\r
11436     NULL,\r
11437     0,\r
11438 };\r
11439 \r
11440 \r
11441 /*[Variant_SuperClass_initialize]*/\r
11442 errnum_t  Variant_SuperClass_initialize( Variant_SuperClass* self, void* Parameter )\r
11443 {\r
11444         self->ClassID = &g_Variant_SuperClass_ID;\r
11445         self->FinalizerVTable = NULL;\r
11446         self->StaticAddress = NULL;\r
11447         UNREFERENCED_VARIABLE( Parameter );\r
11448         return  0;\r
11449 }\r
11450 \r
11451 \r
11452  \r
11453 /***********************************************************************\r
11454   <<< (VariantListIteratorClass) >>> \r
11455 ************************************************************************/\r
11456 \r
11457 /*[VariantListIteratorClass_getNext]*/\r
11458 Variant_SuperClass*  VariantListIteratorClass_getNext( VariantListIteratorClass* self )\r
11459 {\r
11460         VariantClass*  variant;\r
11461 \r
11462         variant = ListIteratorClass_getNext( &self->Iterator );\r
11463         if ( variant == NULL ) {\r
11464                 return  NULL;\r
11465         } else {\r
11466                 return  variant->Object;\r
11467         }\r
11468 }\r
11469 \r
11470 \r
11471  \r
11472 /***********************************************************************\r
11473   <<< [PArray_setFromArray] >>> \r
11474 ************************************************************************/\r
11475 int  PArray_setFromArray( void* PointerArray, size_t PointerArraySize, void* out_ppRight,\r
11476         void* SrcArray, size_t SrcArraySize, size_t SrcArrayElemSize )\r
11477 {\r
11478         int       e = 0;\r
11479         char**    pp;\r
11480         char**    pp_over;\r
11481         char*     s;\r
11482         char*     s_over;\r
11483 \r
11484         pp      = (char**) PointerArray;\r
11485         pp_over = (char**)( (char*)PointerArray + PointerArraySize );\r
11486         s       = (char*)  SrcArray;\r
11487         s_over  = (char*)  SrcArray + SrcArraySize;\r
11488 \r
11489         IF ( (pp_over - pp) * SrcArraySize  <  SrcArraySize ) {\r
11490                 s_over  = (char*)SrcArray + (pp_over - pp) * SrcArraySize;\r
11491                 e = E_FEW_ARRAY;\r
11492         }\r
11493 \r
11494         while ( s < s_over ) {\r
11495                 *pp = s;\r
11496                 pp++;  s += SrcArrayElemSize;\r
11497         }\r
11498 \r
11499         if ( out_ppRight != NULL )  *(char***)out_ppRight = pp - 1;\r
11500 \r
11501         return  e;\r
11502 }\r
11503 \r
11504 \r
11505  \r
11506 /***********************************************************************\r
11507   <<< [PArray_doShakerSort] >>> \r
11508 ************************************************************************/\r
11509 errnum_t  PArray_doShakerSort( const void* PointerArray,  size_t PointerArraySize,\r
11510         const void* ppLeft,  const void* ppRight,  CompareFuncType Compare,  const void* Param )\r
11511 {\r
11512         errnum_t  e;\r
11513         void**    p_left  = (void**)ppLeft;\r
11514         void**    p_right = (void**)ppRight;\r
11515         void**    p1;\r
11516         void**    p2;\r
11517         void**    p_swap;\r
11518         void*     swap;\r
11519         int       cmp;\r
11520 \r
11521         if ( PointerArraySize == 0 ) { e=0; goto fin; }\r
11522 \r
11523         IF_D( ppLeft  != NULL && ( ppLeft  < PointerArray || (char*)ppLeft  >= (char*)PointerArray + PointerArraySize ) ) goto err;\r
11524         IF_D( ppRight != NULL && ( ppRight < PointerArray || (char*)ppRight >= (char*)PointerArray + PointerArraySize ) ) goto err;\r
11525 \r
11526         if ( p_left  == NULL )  p_left  = (void**) PointerArray;\r
11527         if ( p_right == NULL )  p_right = (void**)( (char*) PointerArray + PointerArraySize - sizeof(void*) );\r
11528 \r
11529         for (;;) {\r
11530 \r
11531                 //=== Run to right\r
11532                 p1 = p_left;\r
11533                 p2 = p_left + 1;\r
11534                 p_swap = p_left;\r
11535 \r
11536                 while ( p1 < p_right ) {\r
11537                         e= Compare( p1, p2, Param, &cmp ); IF(e)goto fin;\r
11538                         if ( cmp > 0 ) {\r
11539                                 swap = *p1;  *p1 = *p2;  *p2 = swap;\r
11540                                 p_swap = p1;\r
11541                         }\r
11542                         p1++;  p2++;\r
11543                 }\r
11544                 if ( p_swap == p_left )  break;\r
11545                 p_right = p_swap;\r
11546 \r
11547 \r
11548                 //=== Run to left\r
11549                 p1 = p_right - 1;\r
11550                 p2 = p_right;\r
11551                 p_swap = p_right;\r
11552 \r
11553                 while ( p1 >= p_left ) {\r
11554                         e= Compare( p1, p2, Param, &cmp ); IF(e)goto fin;\r
11555                         if ( cmp > 0 ) {\r
11556                                 swap = *p1;  *p1 = *p2;  *p2 = swap;\r
11557                                 p_swap = p2;\r
11558                         }\r
11559                         p1--;  p2--;\r
11560                 }\r
11561                 if ( p_swap == p_right )  break;\r
11562                 p_left = p_swap;\r
11563         }\r
11564 \r
11565         e=0;\r
11566 fin:\r
11567         return  e;\r
11568 \r
11569 err:  e = E_OTHERS;  goto fin;\r
11570 }\r
11571 \r
11572 \r
11573  \r
11574 /***********************************************************************\r
11575   <<< [PArray_isSorted] >>> \r
11576 ************************************************************************/\r
11577 errnum_t  PArray_isSorted( const void* PointerArray, size_t PointerArraySize,\r
11578         CompareFuncType Compare, const void* Param, bool* out_IsSorted )\r
11579 {\r
11580         errnum_t      e;\r
11581         const void**  p;\r
11582         const void**  p_over;\r
11583         int           result;\r
11584 \r
11585         p = PointerArray;\r
11586         p_over = (const void**)( (uintptr_t) PointerArray + PointerArraySize - sizeof(void*) );\r
11587 \r
11588         while ( p < p_over ) {\r
11589                 e= Compare( p,  p + 1,  Param,  &result );\r
11590                         IF(e){goto fin;}\r
11591 \r
11592                 IF ( result > 0 ) { *out_IsSorted = false;  goto fin; }\r
11593 \r
11594                 p += 1;\r
11595         }\r
11596 \r
11597         *out_IsSorted = true;\r
11598 \r
11599         e=0;\r
11600 fin:\r
11601         return  e;\r
11602 }\r
11603 \r
11604 \r
11605 /***********************************************************************\r
11606   <<< [PArray_doBinarySearch] >>> \r
11607 ************************************************************************/\r
11608 errnum_t  PArray_doBinarySearch( const void* PointerArray, size_t PointerArraySize,\r
11609         const void* Key, CompareFuncType Compare, const void* Param,\r
11610         int* out_FoundOrLeftIndex, int* out_CompareResult )\r
11611 {\r
11612         errnum_t   e;\r
11613         uintptr_t  base = (uintptr_t) PointerArray;\r
11614         uintptr_t  left;  /* index */\r
11615         uintptr_t  right;\r
11616         uintptr_t  middle;\r
11617         int        result;\r
11618 \r
11619         left  = 0;\r
11620         right = (uintptr_t) PointerArraySize / sizeof(void*);\r
11621 \r
11622         #ifndef  NDEBUG\r
11623         {\r
11624                 bool  is_sorted;\r
11625 \r
11626                 result = 1;\r
11627 \r
11628                 e= PArray_isSorted( PointerArray, PointerArraySize, Compare, Param, &is_sorted );\r
11629                         IF(e){goto fin;}\r
11630                 IF ( ! is_sorted ) { e=E_NO_NEXT; goto fin; }\r
11631         }\r
11632         #endif\r
11633 \r
11634 \r
11635         while ( right - left >= 2 ) {\r
11636                 middle = ( left + right ) / 2;\r
11637 \r
11638                 e= Compare( &Key, ( (const void**) base + middle ), Param, &result );\r
11639                         IF(e){goto fin;}\r
11640 \r
11641                 if ( result == 0 ) {\r
11642                         left = middle;\r
11643                         e = 0;  goto fin;\r
11644                 } else if ( result < 0 ) {\r
11645                         right = middle;\r
11646                 } else {\r
11647                         left = middle;\r
11648                 }\r
11649         }\r
11650 \r
11651         e= Compare( &Key, ( (const void**) base + left ), Param, &result );\r
11652                 IF(e){goto fin;}\r
11653 \r
11654         e=0;\r
11655 fin:\r
11656         *out_FoundOrLeftIndex = left;\r
11657         *out_CompareResult = result;\r
11658         return  e;\r
11659 }\r
11660 \r
11661 \r
11662  \r
11663 /***********************************************************************\r
11664   <<< (DictionaryAA_NodeClass:Class) >>> \r
11665 ************************************************************************/\r
11666 \r
11667 /*[DictionaryAA_SearchWorkClass]*/\r
11668 typedef struct _DictionaryAA_SearchWorkClass  DictionaryAA_SearchWorkClass;\r
11669 struct _DictionaryAA_SearchWorkClass {\r
11670         const TCHAR*             SearchKey;\r
11671         DictionaryAA_NodeClass*  FoundNode;\r
11672         bool                     IsErrorIfNotFound;\r
11673 };\r
11674 \r
11675 /*[DictionaryAA_TraverseWorkClass]*/\r
11676 typedef struct _DictionaryAA_TraverseWorkClass  DictionaryAA_TraverseWorkClass;\r
11677 struct _DictionaryAA_TraverseWorkClass {\r
11678         DictionaryAA_TraverseFuncType  Function;\r
11679         void*                          UserParameter;\r
11680 };\r
11681 \r
11682 errnum_t  DictionaryAA_NodeClass_insert( DictionaryAA_NodeClass* Node,\r
11683         DictionaryAA_NodeClass** out_ParentNode, DictionaryAA_SearchWorkClass* work );\r
11684 errnum_t  DictionaryAA_NodeClass_search( DictionaryAA_NodeClass* Node,\r
11685         DictionaryAA_SearchWorkClass* work );\r
11686 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_remove( DictionaryAA_NodeClass* Node,\r
11687         const TCHAR* Key, DictionaryAA_NodeClass** out_RemovingNode );\r
11688 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_skew( DictionaryAA_NodeClass* Node );\r
11689 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_split( DictionaryAA_NodeClass* Node );\r
11690 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_rotateLeft( DictionaryAA_NodeClass* Node );\r
11691 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_rotateRight( DictionaryAA_NodeClass* Node );\r
11692 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_searchMin( DictionaryAA_NodeClass* Node );\r
11693 errnum_t  DictionaryAA_NodeClass_toEmpty( DictionaryAA_NodeClass* Node, errnum_t e );\r
11694 errnum_t  DictionaryAA_NodeClass_onTraverse( DictionaryAA_NodeClass* Node,\r
11695         DictionaryAA_TraverseWorkClass* work );\r
11696 errnum_t  DictionaryAA_NodeClass_print( DictionaryAA_NodeClass* Node, int RootHeight,\r
11697         FILE* OutputStream );\r
11698 \r
11699 \r
11700  \r
11701 /***********************************************************************\r
11702   <<< (DictionaryAA_Class) >>> \r
11703 ************************************************************************/\r
11704 \r
11705 /*[DictionaryAA_Class_initConst]*/\r
11706 void  DictionaryAA_Class_initConst( DictionaryAA_Class* self )\r
11707 {\r
11708         self->Root = &g_DictionaryAA_NullNode;\r
11709 }\r
11710 \r
11711 \r
11712 /*[DictionaryAA_Class_finalize]*/\r
11713 errnum_t  DictionaryAA_Class_finalize( DictionaryAA_Class* self, errnum_t e )\r
11714 {\r
11715         return  DictionaryAA_NodeClass_toEmpty( self->Root, e );\r
11716 }\r
11717 \r
11718 \r
11719 /*[DictionaryAA_Class_insert]*/\r
11720 errnum_t  DictionaryAA_Class_insert( DictionaryAA_Class* self, const TCHAR* Key,\r
11721         DictionaryAA_NodeClass** out_Node )\r
11722 {\r
11723         errnum_t  e;\r
11724         DictionaryAA_SearchWorkClass  work;\r
11725 \r
11726         work.SearchKey = Key;\r
11727 \r
11728         e= DictionaryAA_NodeClass_insert( self->Root, &self->Root, &work );\r
11729 \r
11730         *out_Node = work.FoundNode;\r
11731 \r
11732         return  e;\r
11733 }\r
11734 \r
11735 \r
11736 /*[DictionaryAA_Class_remove]*/\r
11737 errnum_t  DictionaryAA_Class_remove( DictionaryAA_Class* self, const TCHAR* Key )\r
11738 {\r
11739         errnum_t                 e;\r
11740         DictionaryAA_NodeClass*  removing_node = NULL;\r
11741 \r
11742         self->Root = DictionaryAA_NodeClass_remove( self->Root, Key, &removing_node );\r
11743         if ( removing_node == NULL ) { e = E_NOT_FOUND_SYMBOL;  goto fin; }\r
11744 \r
11745         e=0;\r
11746 fin:\r
11747         if ( removing_node != NULL ) {\r
11748                 e= HeapMemory_free( &removing_node->Key, e );\r
11749                 e= HeapMemory_free( &removing_node, e );\r
11750         }\r
11751         return  e;\r
11752 }\r
11753 \r
11754 \r
11755 /*[DictionaryAA_Class_search]*/\r
11756 errnum_t  DictionaryAA_Class_search( DictionaryAA_Class* self, const TCHAR* Key,\r
11757         DictionaryAA_NodeClass** out_Node )\r
11758 {\r
11759         errnum_t  e;\r
11760         DictionaryAA_SearchWorkClass  work;\r
11761 \r
11762         work.SearchKey = Key;\r
11763         work.IsErrorIfNotFound = true;\r
11764 \r
11765         e= DictionaryAA_NodeClass_search( self->Root, &work );\r
11766 \r
11767         *out_Node = work.FoundNode;\r
11768 \r
11769         return  e;\r
11770 }\r
11771 \r
11772 \r
11773 /*[DictionaryAA_Class_isExist]*/\r
11774 bool  DictionaryAA_Class_isExist( DictionaryAA_Class* self, const TCHAR* Key )\r
11775 {\r
11776         DictionaryAA_SearchWorkClass  work;\r
11777 \r
11778         work.SearchKey = Key;\r
11779         work.IsErrorIfNotFound = false;\r
11780 \r
11781         DictionaryAA_NodeClass_search( self->Root, &work );\r
11782 \r
11783         return  ( work.FoundNode != NULL );\r
11784 }\r
11785 \r
11786 \r
11787 /*[DictionaryAA_Class_freeAllKeysHeap]*/\r
11788 #if 0\r
11789 errnum_t  DictionaryAA_Class_freeAllKeysHeap( DictionaryAA_Class* self, errnum_t e )\r
11790 {\r
11791         errnum_t                    ee;\r
11792         DictionaryAA_IteratorClass  iterator;\r
11793         DictionaryAA_NodeClass*     node;\r
11794 \r
11795         DictionaryAA_IteratorClass_initConst( &iterator );\r
11796 \r
11797         ee= DictionaryAA_IteratorClass_initialize( &iterator, self );\r
11798                 IF ( ee != 0  &&  e==0 ) { e = ee;  goto fin; }\r
11799         for ( DictionaryAA_Class_forEach( &iterator, &node ) ) {\r
11800                 e= HeapMemory_free( &node->Key, e );\r
11801         }\r
11802 \r
11803         e=0;\r
11804 fin:\r
11805         e= DictionaryAA_IteratorClass_finalize( &iterator, e );\r
11806         return  e;\r
11807 }\r
11808 #endif\r
11809 \r
11810 \r
11811 /*[DictionaryAA_Class_traverse]*/\r
11812 errnum_t  DictionaryAA_Class_traverse( DictionaryAA_Class* self,\r
11813         DictionaryAA_TraverseFuncType  Function,\r
11814         void*  UserParameter )\r
11815 {\r
11816         DictionaryAA_TraverseWorkClass  work;\r
11817 \r
11818         work.Function = Function;\r
11819         work.UserParameter = UserParameter;\r
11820 \r
11821         return  DictionaryAA_NodeClass_onTraverse( self->Root, &work );\r
11822 }\r
11823 \r
11824 \r
11825 /*[DictionaryAA_Class_toEmpty]*/\r
11826 errnum_t  DictionaryAA_Class_toEmpty( DictionaryAA_Class* self )\r
11827 {\r
11828         errnum_t  e;\r
11829 \r
11830         e= DictionaryAA_NodeClass_toEmpty( self->Root, 0 ); IF(e){goto fin;}\r
11831 \r
11832         e=0;\r
11833 fin:\r
11834         self->Root = &g_DictionaryAA_NullNode;\r
11835         return  e;\r
11836 }\r
11837 \r
11838 \r
11839 /*[DictionaryAA_Class_print]*/\r
11840 errnum_t  DictionaryAA_Class_print( DictionaryAA_Class* self, FILE* OutputStream )\r
11841 {\r
11842         errnum_t  e;\r
11843         int       r;\r
11844 \r
11845         r= _ftprintf_s( OutputStream, _T("DictionaryAA -------------------\n") );\r
11846                 IF(r<0) { e=E_ACCESS_DENIED; goto fin; }\r
11847 \r
11848         e= DictionaryAA_NodeClass_print( self->Root, self->Root->Height, OutputStream );\r
11849                 IF(e){goto fin;}\r
11850 \r
11851         e=0;\r
11852 fin:\r
11853         return  e;\r
11854 }\r
11855 \r
11856 \r
11857  \r
11858 /***********************************************************************\r
11859   <<< [DictionaryAA_Class_finalize2] >>> \r
11860 ************************************************************************/\r
11861 errnum_t  DictionaryAA_Class_finalize2( DictionaryAA_Class* self,  errnum_t  e,\r
11862         bool  in_IsFreeItem,  FinalizeFuncType  in_Type_Finalize )\r
11863 {\r
11864         errnum_t  ee;\r
11865 \r
11866         DictionaryAA_NodeClass*     node;\r
11867         DictionaryAA_IteratorClass  iterator;\r
11868 \r
11869         DictionaryAA_IteratorClass_initConst( &iterator );\r
11870 \r
11871         ee= DictionaryAA_IteratorClass_initialize( &iterator, self );\r
11872                 IF(ee){e=MergeError(e,ee);goto fin;}\r
11873         for ( DictionaryAA_Class_forEach( &iterator, &node ) ) {\r
11874                 if ( in_Type_Finalize != NULL ) {\r
11875                         e= in_Type_Finalize( node->Item, e );\r
11876                 }\r
11877                 if ( in_IsFreeItem ) {\r
11878                         e= HeapMemory_free( &node->Item, e );\r
11879                 }\r
11880         }\r
11881 \r
11882 fin:\r
11883         e= DictionaryAA_IteratorClass_finalize( &iterator, e );\r
11884         e= DictionaryAA_Class_finalize( self, e );\r
11885         return  e;\r
11886 }\r
11887 \r
11888 \r
11889  \r
11890 /***********************************************************************\r
11891   <<< [DictionaryAA_Class_getArray] >>> \r
11892 ************************************************************************/\r
11893 errnum_t  DictionaryAA_Class_getArray( DictionaryAA_Class* self,\r
11894         TCHAR***  in_out_Strings,  int*  in_out_StringCount,  NewStringsEnum  in_HowToAllocate )\r
11895 {\r
11896         errnum_t  e;\r
11897         int       string_count = 0;\r
11898         int       string_count_max;\r
11899 \r
11900         TCHAR**   key_array = NULL;\r
11901         TCHAR**   new_key_array = NULL;\r
11902 \r
11903         DictionaryAA_NodeClass*     node;\r
11904         DictionaryAA_IteratorClass  iterator;\r
11905 \r
11906         DictionaryAA_IteratorClass_initConst( &iterator );\r
11907 \r
11908 \r
11909         /* Set "string_count_max", "key_array" */\r
11910         if ( IsBitSet( in_HowToAllocate, NewStringsEnum_NewPointers ) ) {\r
11911 \r
11912                 string_count_max = 0;\r
11913                 e= DictionaryAA_IteratorClass_initialize( &iterator, self );\r
11914                         IF(e){goto fin;}\r
11915                 for ( DictionaryAA_Class_forEach( &iterator, &node ) ) {\r
11916                         string_count_max += 1;\r
11917                 }\r
11918                 e= DictionaryAA_IteratorClass_finalize( &iterator, 0 ); IF(e){goto fin;}\r
11919 \r
11920                 e= HeapMemory_allocateArray( &new_key_array, string_count_max );\r
11921                         IF(e){goto fin;}\r
11922                 *in_out_Strings = new_key_array;\r
11923                 key_array = new_key_array;\r
11924         }\r
11925         else {\r
11926                 ASSERT_R( in_out_StringCount != NULL,  e=E_OTHERS; goto fin );\r
11927                 string_count_max = *in_out_StringCount;\r
11928                 key_array = *in_out_Strings;\r
11929         }\r
11930         memset( key_array,  0x00,  string_count_max * sizeof(TCHAR*) );\r
11931 \r
11932 \r
11933         /* Set "key_array[ string_count ]" */\r
11934         e= DictionaryAA_IteratorClass_initialize( &iterator, self );\r
11935                 IF(e){goto fin;}\r
11936         for ( DictionaryAA_Class_forEach( &iterator, &node ) ) {\r
11937                 const TCHAR*  value = node->Key;\r
11938 \r
11939                 if ( IsBitSet( in_HowToAllocate, NewStringsEnum_NewCharacters ) ) {\r
11940                         ASSERT_R( IsBitNotSet( in_HowToAllocate, NewStringsEnum_LinkCharacters ),\r
11941                                 e=E_OTHERS; goto fin );\r
11942 \r
11943                         e= MallocAndCopyString( &key_array[ string_count ], value );\r
11944                                 IF(e){goto fin;}\r
11945                 }\r
11946                 else if ( IsBitSet( in_HowToAllocate, NewStringsEnum_LinkCharacters ) ) {\r
11947                         const TCHAR**  key_pp = &key_array[ string_count ];\r
11948 \r
11949                         ASSERT_R( *key_pp == NULL,  e=E_OTHERS; goto fin );\r
11950                         *key_pp = value;\r
11951                 }\r
11952                 else {\r
11953                         ASSERT_R( false,  e=E_LIMITATION;  goto fin );\r
11954                 }\r
11955                 string_count += 1;\r
11956         }\r
11957 \r
11958         *in_out_StringCount = string_count;\r
11959         new_key_array = NULL;\r
11960 \r
11961         e=0;\r
11962 fin:\r
11963         if ( e != 0 ) {\r
11964                 if ( IsBitSet( in_HowToAllocate, NewStringsEnum_NewCharacters ) ) {\r
11965                         if ( key_array != NULL ) {\r
11966                                 for ( string_count -= 1;  string_count >= 0;  string_count -= 1 ) {\r
11967                                         e= HeapMemory_free( &key_array[ string_count ], e );\r
11968                                 }\r
11969                         }\r
11970                 }\r
11971         }\r
11972         e= HeapMemory_free( &new_key_array, e );\r
11973         e= DictionaryAA_IteratorClass_finalize( &iterator, e );\r
11974         return  e;\r
11975 }\r
11976 \r
11977 \r
11978  \r
11979 /***********************************************************************\r
11980   <<< (DictionaryAA_NodeClass) >>> \r
11981 ************************************************************************/\r
11982 \r
11983 /*[g_DictionaryAA_NullNode]*/\r
11984 DictionaryAA_NodeClass  g_DictionaryAA_NullNode = {\r
11985         /* Key */     _T("(NullNode)"),\r
11986         /* Item */    NULL,\r
11987         /* Height */  0,\r
11988         /* Left */    &g_DictionaryAA_NullNode,\r
11989         /* Right */   &g_DictionaryAA_NullNode,\r
11990 };\r
11991 \r
11992 \r
11993 /*[DictionaryAA_NodeClass_insert]*/\r
11994 errnum_t  DictionaryAA_NodeClass_insert( DictionaryAA_NodeClass* in_Node,\r
11995         DictionaryAA_NodeClass** out_ParentNode, DictionaryAA_SearchWorkClass* work )\r
11996 {\r
11997         errnum_t  e;\r
11998 \r
11999         if ( in_Node == &g_DictionaryAA_NullNode ) {\r
12000                 e= HeapMemory_allocate( &in_Node ); IF(e){goto fin;}\r
12001                 in_Node->Key = NULL;\r
12002                 e= MallocAndCopyString( &in_Node->Key, work->SearchKey ); IF(e){goto fin;}\r
12003                 in_Node->Item   = NULL;\r
12004                 in_Node->Height = 1;\r
12005                 in_Node->Left   = &g_DictionaryAA_NullNode;\r
12006                 in_Node->Right  = &g_DictionaryAA_NullNode;\r
12007                 *out_ParentNode = in_Node;\r
12008                 work->FoundNode = in_Node;\r
12009         }\r
12010         else {\r
12011                 int  compare = _tcscmp( work->SearchKey, in_Node->Key );\r
12012 \r
12013                 if ( compare == 0 ) {\r
12014                         *out_ParentNode = in_Node;\r
12015                         work->FoundNode = in_Node;\r
12016                 }\r
12017                 else {\r
12018                         if ( compare < 0 ) {\r
12019                                 e= DictionaryAA_NodeClass_insert( in_Node->Left, &in_Node->Left, work );\r
12020                                         IF(e){goto fin;}\r
12021                         }\r
12022                         else {  /* compare > 0 */\r
12023                                 e= DictionaryAA_NodeClass_insert( in_Node->Right, &in_Node->Right, work );\r
12024                                         IF(e){goto fin;}\r
12025                         }\r
12026                         in_Node = DictionaryAA_NodeClass_skew( in_Node );\r
12027                         in_Node = DictionaryAA_NodeClass_split( in_Node );\r
12028                         *out_ParentNode = in_Node;\r
12029                 }\r
12030         }\r
12031 \r
12032         e=0;\r
12033 fin:\r
12034         return  e;\r
12035 }\r
12036 \r
12037 \r
12038 /*[DictionaryAA_NodeClass_search]*/\r
12039 errnum_t  DictionaryAA_NodeClass_search( DictionaryAA_NodeClass* in_Node,\r
12040         DictionaryAA_SearchWorkClass* work )\r
12041 {\r
12042         errnum_t  e;\r
12043         int       compare;\r
12044 \r
12045         if ( in_Node == &g_DictionaryAA_NullNode ) {\r
12046                 IF ( work->IsErrorIfNotFound )  { e = E_NOT_FOUND_SYMBOL;  goto fin; }\r
12047                 work->FoundNode = NULL;\r
12048                 e = 0;  goto fin;\r
12049         }\r
12050 \r
12051         compare = _tcscmp( work->SearchKey, in_Node->Key );\r
12052 \r
12053         if ( compare == 0 ) {\r
12054                 work->FoundNode = in_Node;\r
12055         }\r
12056         else {\r
12057                 if ( compare < 0 ) {\r
12058                         e= DictionaryAA_NodeClass_search( in_Node->Left, work );\r
12059                                 IF(e){goto fin;}\r
12060                 }\r
12061                 else {  /* compare > 0 */\r
12062                         e= DictionaryAA_NodeClass_search( in_Node->Right, work );\r
12063                                 IF(e){goto fin;}\r
12064                 }\r
12065         }\r
12066 \r
12067         e=0;\r
12068 fin:\r
12069         return  e;\r
12070 }\r
12071 \r
12072 \r
12073 /*[DictionaryAA_NodeClass_remove]*/\r
12074 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_remove( DictionaryAA_NodeClass* in_Node,\r
12075         const TCHAR* Key, DictionaryAA_NodeClass** out_RemovingNode )\r
12076 {\r
12077         if ( in_Node != &g_DictionaryAA_NullNode ) {\r
12078                 int  compare = _tcscmp( Key, in_Node->Key );\r
12079 \r
12080                 if ( compare == 0 ) {\r
12081                         if ( in_Node->Left == &g_DictionaryAA_NullNode ) {\r
12082                                 *out_RemovingNode = in_Node;\r
12083                                 in_Node = in_Node->Right;\r
12084                         } else if ( in_Node->Right == &g_DictionaryAA_NullNode ) {\r
12085                                 *out_RemovingNode = in_Node;\r
12086                                 in_Node = in_Node->Left;\r
12087                         } else {\r
12088                                 DictionaryAA_NodeClass*  reuse_node = in_Node;\r
12089                                 DictionaryAA_NodeClass*  sacrifice_node;\r
12090                                 DictionaryAA_NodeClass   swap;\r
12091 \r
12092                                 sacrifice_node = DictionaryAA_NodeClass_searchMin( in_Node->Right );\r
12093                                 reuse_node->Right = DictionaryAA_NodeClass_remove(\r
12094                                         in_Node->Right, sacrifice_node->Key, &sacrifice_node );\r
12095 \r
12096                                 swap.Key  = reuse_node->Key;\r
12097                                 swap.Item = reuse_node->Item;\r
12098                                 reuse_node->Key  = sacrifice_node->Key;\r
12099                                 reuse_node->Item = sacrifice_node->Item;\r
12100                                 sacrifice_node->Key  = swap.Key;\r
12101                                 sacrifice_node->Item = swap.Item;\r
12102                                 *out_RemovingNode = sacrifice_node;\r
12103                         }\r
12104                 }\r
12105                 else if ( compare < 0 ) {\r
12106                         in_Node->Left = DictionaryAA_NodeClass_remove( in_Node->Left, Key, out_RemovingNode );\r
12107                 }\r
12108                 else {  /* compare > 0 */\r
12109                         in_Node->Right = DictionaryAA_NodeClass_remove( in_Node->Right, Key, out_RemovingNode );\r
12110                 }\r
12111 \r
12112                 if ( in_Node->Left->Height < in_Node->Height - 1  ||\r
12113                         in_Node->Right->Height < in_Node->Height - 1 )\r
12114                 {\r
12115                         in_Node->Height -= 1;\r
12116                         if ( in_Node->Right->Height > in_Node->Height )\r
12117                                 { in_Node->Right->Height = in_Node->Height; }\r
12118                         in_Node = DictionaryAA_NodeClass_skew( in_Node );\r
12119                         in_Node->Right = DictionaryAA_NodeClass_skew( in_Node->Right );\r
12120                         in_Node->Right->Right = DictionaryAA_NodeClass_skew( in_Node->Right->Right );\r
12121                         in_Node = DictionaryAA_NodeClass_split( in_Node );\r
12122                         in_Node->Right = DictionaryAA_NodeClass_split( in_Node->Right );\r
12123                 }\r
12124         }\r
12125         return  in_Node;\r
12126 }\r
12127 \r
12128 \r
12129 /*[DictionaryAA_NodeClass_skew]*/\r
12130 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_skew( DictionaryAA_NodeClass* in_Node )\r
12131 {\r
12132         if ( in_Node->Left->Height == in_Node->Height ) {\r
12133                 in_Node = DictionaryAA_NodeClass_rotateRight( in_Node );\r
12134         }\r
12135 \r
12136         return  in_Node;\r
12137 }\r
12138 \r
12139 \r
12140 /*[DictionaryAA_NodeClass_split]*/\r
12141 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_split( DictionaryAA_NodeClass* in_Node )\r
12142 {\r
12143         if ( in_Node->Height == in_Node->Right->Right->Height ) {\r
12144                 in_Node = DictionaryAA_NodeClass_rotateLeft( in_Node );\r
12145                 in_Node->Height += 1;\r
12146         }\r
12147 \r
12148         return  in_Node;\r
12149 }\r
12150 \r
12151 \r
12152 /*[DictionaryAA_NodeClass_rotateLeft]*/\r
12153 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_rotateLeft( DictionaryAA_NodeClass* in_Node )\r
12154 {\r
12155         DictionaryAA_NodeClass*  swap;\r
12156 \r
12157         swap = in_Node->Right;\r
12158         in_Node->Right = swap->Left;\r
12159         swap->Left = in_Node;\r
12160 \r
12161         return  swap;\r
12162 }\r
12163 \r
12164 \r
12165 /*[DictionaryAA_NodeClass_rotateRight]*/\r
12166 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_rotateRight( DictionaryAA_NodeClass* in_Node )\r
12167 {\r
12168         DictionaryAA_NodeClass*  swap;\r
12169 \r
12170         swap = in_Node->Left;\r
12171         in_Node->Left = swap->Right;\r
12172         swap->Right = in_Node;\r
12173 \r
12174         return  swap;\r
12175 }\r
12176 \r
12177 \r
12178 DictionaryAA_NodeClass*  DictionaryAA_NodeClass_searchMin( DictionaryAA_NodeClass* in_Node )\r
12179 {\r
12180         while ( in_Node->Left != &g_DictionaryAA_NullNode )\r
12181                 { in_Node = in_Node->Left; }\r
12182         return  in_Node;\r
12183 }\r
12184 \r
12185 \r
12186 /*[DictionaryAA_NodeClass_toEmpty]*/\r
12187 errnum_t  DictionaryAA_NodeClass_toEmpty( DictionaryAA_NodeClass* in_Node, errnum_t e )\r
12188 {\r
12189         if ( in_Node != &g_DictionaryAA_NullNode ) {\r
12190                 e= DictionaryAA_NodeClass_toEmpty( in_Node->Left, e );\r
12191                 e= DictionaryAA_NodeClass_toEmpty( in_Node->Right, e );\r
12192                 e= HeapMemory_free( &in_Node->Key, e );\r
12193                 e= HeapMemory_free( &in_Node, e );\r
12194         }\r
12195         return  e;\r
12196 }\r
12197 \r
12198 \r
12199 /*[DictionaryAA_NodeClass_onTraverse]*/\r
12200 errnum_t  DictionaryAA_NodeClass_onTraverse( DictionaryAA_NodeClass* in_Node,\r
12201         DictionaryAA_TraverseWorkClass* work )\r
12202 {\r
12203         errnum_t  e;\r
12204 \r
12205         if ( in_Node != &g_DictionaryAA_NullNode ) {\r
12206                 e= DictionaryAA_NodeClass_onTraverse( in_Node->Left, work ); IF(e){goto fin;}\r
12207                 e= work->Function( in_Node, work->UserParameter ); IF(e){goto fin;}\r
12208                 e= DictionaryAA_NodeClass_onTraverse( in_Node->Right, work ); IF(e){goto fin;}\r
12209         }\r
12210 \r
12211         e=0;\r
12212 fin:\r
12213         return  e;\r
12214 }\r
12215 \r
12216 \r
12217 /*[DictionaryAA_NodeClass_print]*/\r
12218 errnum_t  DictionaryAA_NodeClass_print( DictionaryAA_NodeClass* in_Node, int RootHeight,\r
12219         FILE* OutputStream )\r
12220 {\r
12221         errnum_t  e;\r
12222         int       r;\r
12223 \r
12224         if ( in_Node != &g_DictionaryAA_NullNode ) {\r
12225 \r
12226                 e= DictionaryAA_NodeClass_print( in_Node->Left, RootHeight, OutputStream );\r
12227                         IF(e){goto fin;}\r
12228 \r
12229                 r= _ftprintf_s( OutputStream, _T("%*s%s\n"), ( RootHeight - in_Node->Height ) * 4,\r
12230                         _T(""), in_Node->Key ); IF(r<0) { e=E_ACCESS_DENIED; goto fin; }\r
12231 \r
12232                 e= DictionaryAA_NodeClass_print( in_Node->Right, RootHeight, OutputStream );\r
12233                         IF(e){goto fin;}\r
12234         }\r
12235 \r
12236         e=0;\r
12237 fin:\r
12238         return  e;\r
12239 }\r
12240 \r
12241 \r
12242  \r
12243 /***********************************************************************\r
12244   <<< (DictionaryAA_IteratorClass) >>> \r
12245 ************************************************************************/\r
12246 \r
12247 errnum_t  DictionaryAA_IteratorClass_initialize_sub( DictionaryAA_NodeClass* in_Node,\r
12248         void*  Array );\r
12249 \r
12250 \r
12251 /*[DictionaryAA_IteratorClass_initialize]*/\r
12252 errnum_t  DictionaryAA_IteratorClass_initialize( DictionaryAA_IteratorClass* self,\r
12253         DictionaryAA_Class* Collection )\r
12254 {\r
12255         errnum_t  e;\r
12256 \r
12257         e= Set2_init( &self->Nodes, 0x100 ); IF(e){goto fin;}\r
12258 \r
12259         e= DictionaryAA_Class_traverse( Collection, DictionaryAA_IteratorClass_initialize_sub,\r
12260                 &self->Nodes ); IF(e){goto fin;}\r
12261 \r
12262         self->NextNode = self->Nodes.First;\r
12263 \r
12264         e=0;\r
12265 fin:\r
12266         return  e;\r
12267 }\r
12268 \r
12269 \r
12270 /*[DictionaryAA_IteratorClass_initialize_sub]*/\r
12271 errnum_t  DictionaryAA_IteratorClass_initialize_sub( DictionaryAA_NodeClass* in_Node,\r
12272         void*  Array )\r
12273 {\r
12274         errnum_t  e;\r
12275         Set2*     array = (Set2*) Array;\r
12276         DictionaryAA_NodeClass**  pp_node;\r
12277 \r
12278         e= Set2_alloc( array, &pp_node, DictionaryAA_NodeClass* ); IF(e){goto fin;}\r
12279         *pp_node = in_Node;\r
12280 \r
12281         e=0;\r
12282 fin:\r
12283         return  e;\r
12284 }\r
12285 \r
12286 \r
12287 /*[DictionaryAA_IteratorClass_getNext]*/\r
12288 DictionaryAA_NodeClass*  DictionaryAA_IteratorClass_getNext(\r
12289         DictionaryAA_IteratorClass* self )\r
12290 {\r
12291         DictionaryAA_NodeClass*  return_value;\r
12292 \r
12293         if ( self->NextNode < (DictionaryAA_NodeClass**) self->Nodes.Next ) {\r
12294                 return_value = *self->NextNode;\r
12295                 self->NextNode += 1;\r
12296         }\r
12297         else {\r
12298                 return_value = NULL;\r
12299         }\r
12300 \r
12301         return  return_value;\r
12302 }\r
12303 \r
12304 \r
12305  \r
12306 /*=================================================================*/\r
12307 /* <<< [Print/Print2.c] >>> */ \r
12308 /*=================================================================*/\r
12309  \r
12310 /***********************************************************************\r
12311   <<< [PrintfCounterClass] >>> \r
12312 ************************************************************************/\r
12313 #if USE_PRINTF_COUNTER\r
12314         PrintfCounterClass  g_PrintfCounter;\r
12315 #endif\r
12316 \r
12317 \r
12318  \r
12319 /***********************************************************************\r
12320   <<< [printf_to_file] >>> \r
12321 ************************************************************************/\r
12322 \r
12323 #if USE_PRINTF_MULTI_THREAD\r
12324         enum { g_PrintfMultiThreadCountMax = 8 };\r
12325         DWORD  g_printf_file_tid[ g_PrintfMultiThreadCountMax ];\r
12326         bool   g_printf_file_clear;\r
12327 #endif\r
12328 \r
12329 TCHAR  g_printf_file_path[MAX_PATH];\r
12330 int    g_printf_file_indent;\r
12331 \r
12332 static DWORD  gs_locked_thread = 0;\r
12333 \r
12334 \r
12335 void  printf_lock_init_const( PrintfFileWorkClass* out_Work )\r
12336 {\r
12337         out_Work->File = NULL;\r
12338         #if USE_PRINTF_MULTI_THREAD\r
12339                 out_Work->Mutex = NULL;\r
12340                 out_Work->ThreadIndex = 0;\r
12341         #endif\r
12342 }\r
12343 \r
12344 errnum_t  printf_lock( PrintfFileWorkClass* out_Work )\r
12345 {\r
12346         errnum_t  e;\r
12347         TCHAR*    path;\r
12348         DWORD     tid = GetCurrentThreadId();\r
12349         FILE*     file = NULL;\r
12350 #if USE_PRINTF_MULTI_THREAD\r
12351         HANDLE    mutex = NULL;\r
12352         int       thread_index = 0;\r
12353 #endif\r
12354 \r
12355         printf_lock_init_const( out_Work );\r
12356 \r
12357         e= printf_get_path( &path ); IF(e){goto fin;}\r
12358 \r
12359         #if USE_PRINTF_MULTI_THREAD\r
12360                 mutex = CreateMutex( NULL, TRUE, TEXT("printf_file_mutex") );\r
12361                         IF ( mutex == NULL ) { e=E_GET_LAST_ERROR; goto fin; }\r
12362                 if ( gs_locked_thread == tid )\r
12363                         { DebugBreak(); } /* Re-entrant error */\r
12364                         /* Call "GetLogOptionPath" and "AppKey_newWritable" */\r
12365                 gs_locked_thread = tid;\r
12366 \r
12367                 if ( ! g_printf_file_clear ) {\r
12368                         if ( path != NULL )  _tremove( path );\r
12369                         g_printf_file_clear = true;\r
12370                 }\r
12371                 for ( thread_index = 0;  thread_index < _countof( g_printf_file_tid );  thread_index += 1 ) {\r
12372                         if ( g_printf_file_tid[ thread_index ] == 0  ||  g_printf_file_tid[ thread_index ] == tid )\r
12373                                 { break; }\r
12374                 }\r
12375                 g_printf_file_tid[ thread_index ] = tid;\r
12376         #endif\r
12377 \r
12378         if ( path[0] == _T('\0') )\r
12379                 { file = stdout; }\r
12380         else {\r
12381                 errno_t  en;\r
12382 \r
12383                 en= _tfopen_s( &file, path, _T("a") );\r
12384                 if(en){ DebugBreak(); }\r
12385         }\r
12386 \r
12387 fin:\r
12388         out_Work->File = file;\r
12389         #if USE_PRINTF_MULTI_THREAD\r
12390                 out_Work->Mutex = mutex;\r
12391                 out_Work->ThreadIndex = thread_index;\r
12392         #endif\r
12393         if ( e != 0 ) {\r
12394                 printf_unlock( out_Work, e );\r
12395         }\r
12396         return  e;\r
12397 }\r
12398 \r
12399 \r
12400 errnum_t  printf_unlock( PrintfFileWorkClass* work,  errnum_t e )\r
12401 {\r
12402         FILE*     file  = work->File;\r
12403 #if USE_PRINTF_MULTI_THREAD\r
12404         HANDLE    mutex = work->Mutex;\r
12405 #endif\r
12406 \r
12407         if ( file != stdout  &&  file != NULL )\r
12408                 { fclose( file ); }\r
12409 \r
12410         #if USE_PRINTF_MULTI_THREAD\r
12411                 if ( mutex != NULL ) {\r
12412                         gs_locked_thread = 0;\r
12413                         ReleaseMutex( mutex );\r
12414                         CloseHandle( mutex );\r
12415                 }\r
12416         #endif\r
12417 \r
12418         printf_lock_init_const( work );\r
12419 \r
12420         return  e;\r
12421 }\r
12422 \r
12423 \r
12424 void  printf_to_file( const char* format, ... )\r
12425 {\r
12426         enum { num_8_tab = 8 };\r
12427 \r
12428         va_list   va;\r
12429         errnum_t  e;\r
12430         int       r;\r
12431         FILE*     file = NULL;\r
12432         int       thread_index = 0;\r
12433 \r
12434         ErrStackAreaClass    err_stack;\r
12435         PrintfFileWorkClass  work;\r
12436 \r
12437         PushErr( &err_stack );\r
12438 \r
12439         e= printf_lock( &work ); if(e){goto fin;}\r
12440 \r
12441         file = work.File;\r
12442         thread_index = work.ThreadIndex;\r
12443 \r
12444 \r
12445         #if USE_PRINTF_COUNTER\r
12446         if ( g_PrintfCounter.Count == 0 ) {\r
12447                 char*  process_ID;\r
12448 \r
12449                 #if USE_PRINTF_MULTI_PROCESS\r
12450                         process_ID = "ProcessID:";\r
12451                 #else\r
12452                         process_ID = "";\r
12453                 #endif\r
12454 \r
12455                 fprintf_s( file, "%*s|{%sg_PrintfCounter.BreakIndent:g_PrintfCounter.BreakCount}\n",\r
12456                         thread_index * num_8_tab + g_printf_file_indent, "", process_ID );\r
12457         }\r
12458         #endif\r
12459 \r
12460         #if USE_PRINTF_MULTI_THREAD\r
12461                 fprintf_s( file, "%*s", thread_index * num_8_tab + g_printf_file_indent + 1, "|" );\r
12462         #endif\r
12463 \r
12464         #if USE_PRINTF_COUNTER\r
12465         {\r
12466                 char  process_ID[ INT_DECIMAL_LENGTH_MAX + 5 ];\r
12467 \r
12468                 #if USE_PRINTF_MULTI_PROCESS\r
12469                         sprintf_s( process_ID, _countof( process_ID ), "%d:", GetCurrentProcessId() );\r
12470                 #else\r
12471                         process_ID[0] = '\0';\r
12472                 #endif\r
12473 \r
12474                 g_PrintfCounter.Count ++;\r
12475                 fprintf_s( file, "{%s%d:%d}", process_ID, thread_index * num_8_tab + g_printf_file_indent,\r
12476                         g_PrintfCounter.Count );\r
12477         }\r
12478         #endif\r
12479 \r
12480         va_start( va, format );\r
12481         r= vfprintf_s( file, format, va );\r
12482         va_end( va );\r
12483         IF(r<0){ e=E_ERRNO; goto fin; }\r
12484 \r
12485         e=0;\r
12486 fin:\r
12487         e= printf_unlock( &work, e );\r
12488 \r
12489         IfErrThenBreak();\r
12490         PopErr( &err_stack );\r
12491         #if USE_PRINTF_COUNTER\r
12492         if ( g_PrintfCounter.BreakCount > 0  &&\r
12493                 g_PrintfCounter.Count >= g_PrintfCounter.BreakCount  &&\r
12494                 thread_index * num_8_tab + g_printf_file_indent == g_PrintfCounter.BreakIndent )\r
12495                 { DebugBreakR(); }\r
12496         #endif\r
12497 \r
12498         return;\r
12499 }\r
12500 \r
12501 \r
12502 //[printf_file_start]\r
12503 void  printf_file_start( bool IsDelete, int IndentWidth )\r
12504 {\r
12505         g_printf_file_indent = IndentWidth;\r
12506 \r
12507         if ( IsDelete ) {\r
12508                 int  e;\r
12509                 TCHAR*  path;\r
12510 \r
12511                 e= printf_get_path( &path ); IF(e)return;\r
12512                 if ( path != NULL )  _tremove( path );\r
12513         }\r
12514         #if USE_PRINTF_MULTI_THREAD\r
12515                 g_printf_file_clear = true;\r
12516         #endif\r
12517 }\r
12518 \r
12519 \r
12520 // [printf_get_path]\r
12521 int  printf_get_path( TCHAR** out_Path )\r
12522 {\r
12523         int   e;\r
12524         BOOL  b;\r
12525         TCHAR  desktop[MAX_PATH];\r
12526 \r
12527         if ( g_printf_file_path[0] == '\0' ) {\r
12528                 b= SHGetSpecialFolderPath( NULL, desktop, CSIDL_DESKTOP, FALSE ); IF(!b){goto err_gt;}\r
12529                 e= StrT_getFullPath( g_printf_file_path, sizeof(g_printf_file_path),\r
12530                         _T("DebugOut.txt"), desktop ); IF(e){goto err_gt;}\r
12531         }\r
12532         if ( g_printf_file_path[0] == '*' ) {\r
12533                 *out_Path = _T("");\r
12534         }\r
12535         else {\r
12536                 *out_Path = g_printf_file_path;\r
12537         }\r
12538         e=0;\r
12539 fin:\r
12540         return  e;\r
12541 \r
12542 err_gt: e= E_GET_LAST_ERROR; goto fin;\r
12543 }\r
12544 \r
12545 \r
12546 // [printf_set_path]\r
12547 int  printf_set_path( const TCHAR* Path )\r
12548 {\r
12549         int  e;\r
12550 \r
12551         if ( Path[0] == _T('\0') ) {\r
12552                 g_printf_file_path[0] = _T('*'); \r
12553                 g_printf_file_path[1] = _T('\0'); \r
12554                 e = 0;\r
12555         }\r
12556         else {\r
12557                 e= StrT_cpy( g_printf_file_path, sizeof(g_printf_file_path), Path );\r
12558                         IF(e){goto fin;}\r
12559         }\r
12560 fin:\r
12561         return  e;\r
12562 }\r
12563 \r
12564 \r
12565  \r
12566 /***********************************************************************\r
12567   <<< [GetLogOptionPath] >>> \r
12568 ************************************************************************/\r
12569 TCHAR*  GetLogOptionPath()\r
12570 {\r
12571         int     e;\r
12572         TCHAR*  log_path = NULL;\r
12573         TCHAR   log_opt_path[MAX_PATH];\r
12574 \r
12575         e= GetCommandLineNamed( _T("Log"), false, log_opt_path, sizeof(log_opt_path) );\r
12576                 //[out] log_opt_path\r
12577         if ( e != E_NOT_FOUND_SYMBOL ) { IF(e)goto fin; }\r
12578         ClearError();\r
12579         if ( !e ) {\r
12580                 e= printf_set_path( log_opt_path ); IF(e)goto fin;\r
12581         }\r
12582 \r
12583         e= printf_get_path( &log_path ); IF(e)goto fin;\r
12584 \r
12585         e=0;\r
12586 fin:\r
12587         if ( e ) {  // if error, return default path\r
12588                 printf_set_path( _T("") );\r
12589                 printf_get_path( &log_path );\r
12590         }\r
12591 \r
12592         return  log_path;\r
12593 }\r
12594 \r
12595 \r
12596  \r
12597 /***********************************************************************\r
12598   <<< [vsprintf_r] >>> \r
12599 ************************************************************************/\r
12600 errnum_t  vsprintf_r( char* s, size_t s_size, const char* format, va_list va )\r
12601 {\r
12602         #if _MSC_VER\r
12603                 #pragma warning(push)\r
12604                 #pragma warning(disable: 4996)\r
12605         #endif\r
12606 \r
12607         int  r = _vsnprintf( s, s_size, format, va );\r
12608 \r
12609         #if _MSC_VER\r
12610                 #pragma warning(pop)\r
12611         #endif\r
12612 \r
12613         IF( r == (int) s_size )\r
12614                 { s[s_size-1] = '\0';  return E_FEW_ARRAY; }\r
12615         IF( r == -1 )\r
12616                 { return E_NOT_FOUND_SYMBOL; }  /* Bad character code */\r
12617 \r
12618         return  0;\r
12619 }\r
12620 \r
12621 \r
12622  \r
12623 /***********************************************************************\r
12624   <<< [vswprintf_r] >>> \r
12625 ************************************************************************/\r
12626 #ifndef  __linux__\r
12627 errnum_t  vswprintf_r( wchar_t* s, size_t s_size, const wchar_t* format, va_list va )\r
12628 {\r
12629         size_t  tsize = s_size / sizeof(wchar_t);\r
12630 \r
12631         #if _MSC_VER\r
12632                 #pragma warning(push)\r
12633                 #pragma warning(disable: 4996)\r
12634         #endif\r
12635 \r
12636         int  r = _vsnwprintf( s, tsize, format, va );\r
12637 \r
12638         #if _MSC_VER\r
12639                 #pragma warning(pop)\r
12640         #endif\r
12641 \r
12642         if ( r == (int) tsize || r == -1 ) { s[tsize-1] = '\0';  return E_FEW_ARRAY; }\r
12643         else  return  0;\r
12644 }\r
12645 #endif\r
12646 \r
12647 \r
12648  \r
12649 /***********************************************************************\r
12650   <<< [stprintf_r] >>> \r
12651 ************************************************************************/\r
12652 errnum_t  stprintf_r( TCHAR* s, size_t s_size, const TCHAR* format, ... )\r
12653 {\r
12654         errnum_t  e;\r
12655         va_list   va;\r
12656 \r
12657         va_start( va, format );\r
12658         e = vstprintf_r( s, s_size, format, va );\r
12659         va_end( va );\r
12660         return  e;\r
12661 }\r
12662 \r
12663 \r
12664  \r
12665 /***********************************************************************\r
12666   <<< [stcpy_part_r] >>> \r
12667 ************************************************************************/\r
12668 errnum_t  stcpy_part_r( TCHAR* s, size_t s_size, TCHAR* s_start, TCHAR** p_s_last,\r
12669                    const TCHAR* src, const TCHAR* src_over )\r
12670 {\r
12671         size_t  s_space = (char*)s + s_size - (char*)s_start;\r
12672         size_t  src_size;\r
12673 \r
12674         IF_D( s_start < s || (char*)s_start >= (char*)s + s_size )  { return 1; }\r
12675 \r
12676         if ( src_over == NULL )  { src_over = StrT_chr( src, _T('\0') ); }\r
12677         IF_D( src > src_over )  { return 1; }\r
12678         src_size = (char*)src_over - (char*)src;\r
12679         IF ( src_size >= s_space ) {\r
12680                 s_space -= sizeof(TCHAR);\r
12681                 memcpy( s, src, s_space );\r
12682 \r
12683                 s_start = (TCHAR*)((char*)s_start + s_space );\r
12684                 *s_start = '\0';\r
12685 \r
12686                 if ( p_s_last != NULL ) { *p_s_last=s_start; }\r
12687                 return  E_FEW_ARRAY;\r
12688         }\r
12689 \r
12690         memcpy( s_start, src, src_size + sizeof(TCHAR) );\r
12691         s_start = (TCHAR*)((char*)s_start + src_size);  *s_start = _T('\0');\r
12692         if ( p_s_last != NULL )  { *p_s_last = s_start; }\r
12693 \r
12694         return  0;\r
12695 }\r
12696 \r
12697 \r
12698  \r
12699 /***********************************************************************\r
12700   <<< [stprintf_part_r] >>> \r
12701 ************************************************************************/\r
12702 errnum_t  stprintf_part_r( TCHAR* s, size_t s_size, TCHAR* s_start, TCHAR** p_s_last,\r
12703                       const TCHAR* format, ... )\r
12704 {\r
12705         errnum_t  e;\r
12706         va_list   va;\r
12707         va_start( va, format );\r
12708 \r
12709         IF_D( s_start < s || (char*)s_start >= (char*)s + s_size ) {return E_OTHERS;}\r
12710 \r
12711         e = vstprintf_r( s_start, s_size - ( (char*)s_start - (char*)s), format, va );\r
12712         va_end( va );  if ( p_s_last != NULL )  *p_s_last = StrT_chr( s_start, '\0' );\r
12713         return  e;\r
12714 }\r
12715 \r
12716 \r
12717  \r
12718 /***********************************************************************\r
12719   <<< [ftcopy_part_r] >>> \r
12720 ************************************************************************/\r
12721 errnum_t  ftcopy_part_r( FILE* OutputStream, const TCHAR* Str, const TCHAR* StrOver )\r
12722 {\r
12723         errnum_t      e;\r
12724         const TCHAR*  p;\r
12725         bool          is_last;\r
12726         int           size;\r
12727         TCHAR         buffer[256];\r
12728 \r
12729         ASSERT_R( Str <= StrOver, e=E_OTHERS; goto fin );\r
12730 \r
12731         p = Str;\r
12732         for (;;) {\r
12733                 size = (uint8_t*) StrOver - (uint8_t*) p;\r
12734                 if ( size <= sizeof(buffer) - sizeof(TCHAR) ) {\r
12735                         is_last = true;\r
12736                 }\r
12737                 else {\r
12738                         size = sizeof(buffer) - sizeof(TCHAR);\r
12739                         is_last = false;\r
12740                 }\r
12741 \r
12742                 memcpy( buffer, p, size );\r
12743                 *(TCHAR*)( (uint8_t*) buffer + size ) = _T('\0');\r
12744                 _fputts( buffer, OutputStream ); IF(ferror(OutputStream)){e=E_ERRNO; goto fin;}\r
12745 \r
12746                 if ( is_last )\r
12747                         { break; }\r
12748 \r
12749                 p = (const TCHAR*)( (uint8_t*) p + size );\r
12750         }\r
12751 \r
12752         e=0;\r
12753 fin:\r
12754         return  e;\r
12755 }\r
12756 \r
12757 \r
12758  \r
12759 /***********************************************************************\r
12760 * Function: OpenConsole\r
12761 *\r
12762 * Argument:\r
12763 *    out_IsExistOrNewConsole - NULL is permitted\r
12764 ************************************************************************/\r
12765 errnum_t  OpenConsole( bool  in_OpenIfNoConsole,  bool*  out_IsExistOrNewConsole )\r
12766 {\r
12767         errnum_t  e;\r
12768         BOOL      b;\r
12769         bool      is_console;\r
12770         HANDLE    stdout_handle;\r
12771         int       stdout_file_descriptor;\r
12772         FILE*     stdout_stream;\r
12773 \r
12774         PROCESSENTRY32  current_process;\r
12775 \r
12776         current_process.dwSize = sizeof( current_process );\r
12777         e= GetProcessInformation( GetCurrentProcessId(),  /*Set*/ &current_process ); IF(e){goto fin;}\r
12778 \r
12779 \r
12780         is_console = (bool) AttachConsole( current_process.th32ParentProcessID );\r
12781 \r
12782         if ( out_IsExistOrNewConsole != NULL ) {\r
12783                 if ( in_OpenIfNoConsole ) {\r
12784                         *out_IsExistOrNewConsole = ! is_console;  /* is new console */\r
12785                 } else {\r
12786                         *out_IsExistOrNewConsole = is_console;  /* is exist console */\r
12787                 }\r
12788         }\r
12789 \r
12790         if ( ! is_console ) {\r
12791                 if ( in_OpenIfNoConsole ) {\r
12792 \r
12793                         b= AllocConsole();\r
12794                 }\r
12795                 else\r
12796                         { e=0; goto fin; }\r
12797                 IF(!b) { e=E_OTHERS; goto fin; }\r
12798         }\r
12799 \r
12800         stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );\r
12801                 IF ( stdout_handle == NULL ) { e=E_OTHERS; goto fin; }\r
12802         stdout_file_descriptor = _open_osfhandle( (intptr_t) stdout_handle, _O_TEXT );\r
12803         stdout_stream = _fdopen( stdout_file_descriptor, "w" );\r
12804         setvbuf( stdout_stream, NULL, _IONBF, 0 );\r
12805 \r
12806         *stdout = *stdout_stream;\r
12807 \r
12808         e=0;\r
12809 fin:\r
12810         return  e;\r
12811 }\r
12812 \r
12813 \r
12814  \r
12815 /*=================================================================*/\r
12816 /* <<< [Lock_1/Lock_1.c] >>> */ \r
12817 /*=================================================================*/\r
12818  \r
12819 /*-------------------------------------------------------------------------*/\r
12820 /* <<<< ### (SingletonInitializerClass) implement >>>> */ \r
12821 /*-------------------------------------------------------------------------*/\r
12822 \r
12823 \r
12824 volatile int  g_SingletonInitializerClass_FailSleepTime = SingletonInitializerClass_FailSleepTime;\r
12825 \r
12826 \r
12827 /*[SingletonInitializerClass_isFirst]*/\r
12828 bool  SingletonInitializerClass_isFirst( SingletonInitializerClass* self )\r
12829 {\r
12830         for (;;) {\r
12831                 if ( InterlockedCompareExchange( &self->InitializeStep, 1, 0 ) == 0 ) {\r
12832                         return  true;\r
12833                 }\r
12834                 else {\r
12835                         while ( self->InitializeStep == 1 ) {\r
12836                                 Sleep( 0 );  /* Wait for initialized by other thread. */\r
12837                         }\r
12838 \r
12839                         if ( self->InitializeStep == 2 ) {\r
12840                                 return  false;\r
12841                         }\r
12842 \r
12843                         Sleep( g_SingletonInitializerClass_FailSleepTime );\r
12844                         g_SingletonInitializerClass_FailSleepTime = 0;\r
12845                 }\r
12846         }\r
12847 }\r
12848 \r
12849 \r
12850 /*[SingletonInitializerClass_onFinishedInitialize]*/\r
12851 void  SingletonInitializerClass_onFinishedInitialize( SingletonInitializerClass* self, errnum_t e )\r
12852 {\r
12853         if ( e == 0 )\r
12854                 { self->InitializeStep = 2; }\r
12855         else\r
12856                 { self->InitializeStep = 0; }\r
12857 }\r
12858 \r
12859 \r
12860 /*[SingletonInitializerClass_isInitialized]*/\r
12861 bool  SingletonInitializerClass_isInitialized( SingletonInitializerClass* self )\r
12862 {\r
12863         return  ( self->InitializeStep == 2 );\r
12864 }\r
12865 \r
12866 \r
12867 /*-------------------------------------------------------------------------*/\r
12868 /* <<< End of Class implement >>> */ \r
12869 /*-------------------------------------------------------------------------*/\r
12870 \r
12871 \r
12872  \r
12873 /*=================================================================*/\r
12874 /* <<< [CRT_plus_1/CRT_plus_1.c] >>> */ \r
12875 /*=================================================================*/\r
12876  \r
12877 /***********************************************************************\r
12878   <<< [ttoi_ex] >>> \r
12879 ************************************************************************/\r
12880 int  ttoi_ex( const TCHAR* string,  bit_flags_fast32_t options )\r
12881 {\r
12882         int  return_value;\r
12883 \r
12884         UNREFERENCED_VARIABLE( options);\r
12885 \r
12886         if ( string[0] == _T('0')  &&\r
12887                 ( string[1] == _T('x')  ||  string[1] == _T('X') ) )\r
12888         {\r
12889                 return_value = (int) _tcstoul( &string[2], NULL, 16 );\r
12890         }\r
12891         else {\r
12892                 return_value = _ttoi( string );\r
12893         }\r
12894 \r
12895         return  return_value;\r
12896 }\r
12897 \r
12898 \r
12899  \r
12900 /***********************************************************************\r
12901   <<< (ClassID_Class) >>> \r
12902 ************************************************************************/\r
12903 \r
12904 /*[ClassID_Class_isSuperClass]*/\r
12905 bool  ClassID_Class_isSuperClass( const ClassID_Class* ClassID, const ClassID_Class* SuperClassID )\r
12906 {\r
12907         if ( ClassID == SuperClassID ) {\r
12908                 return  true;\r
12909         }\r
12910         else {\r
12911                 int  i;\r
12912 \r
12913                 for ( i = ClassID->SuperClassID_Array_Count - 1;  i >= 0;  i -= 1 ) {\r
12914                         if ( ClassID->SuperClassID_Array[ i ] == SuperClassID ) {\r
12915                                 return  true;\r
12916                         }\r
12917                 }\r
12918                 return  false;\r
12919         }\r
12920 }\r
12921 \r
12922 \r
12923 /*[ClassID_Class_createObject]*/\r
12924 errnum_t  ClassID_Class_createObject( const ClassID_Class* ClassID, void* out_Object, void* Parameter )\r
12925 {\r
12926         errnum_t  e;\r
12927         ClassID_SuperClass*  object = NULL;\r
12928 \r
12929         e= HeapMemory_allocateBytes( &object, ClassID->Size ); IF(e){goto fin;}\r
12930         if ( ClassID->InitializeFunction != NULL ) {\r
12931                 e= ClassID->InitializeFunction( object, Parameter ); IF(e){goto fin;}\r
12932         }\r
12933         else {\r
12934                 memset( object, 0, ClassID->Size );\r
12935                 object->ClassID = ClassID;\r
12936         }\r
12937         *(void**) out_Object = object;\r
12938         object = NULL;\r
12939 \r
12940         e=0;\r
12941 fin:\r
12942         if ( object != NULL ) { e= HeapMemory_free( &object, e ); }\r
12943         return  e;\r
12944 }\r
12945 \r
12946 \r
12947 /*[ClassID_Class_getVTable]*/\r
12948 void*  ClassID_Class_getVTable( const ClassID_Class* ClassID, const InterfaceID_Class* InterfaceID )\r
12949 {\r
12950         int  i;\r
12951 \r
12952         for ( i = ClassID->InterfaceToVTable_Array_Conut - 1;  i >= 0;  i -= 1 ) {\r
12953                 if ( ClassID->InterfaceToVTable_Array[ i ].InterfaceID == InterfaceID ) {\r
12954                         return  (void*) ClassID->InterfaceToVTable_Array[ i ].VTable;\r
12955                 }\r
12956         }\r
12957         return  NULL;\r
12958 }\r
12959 \r
12960 \r
12961  \r
12962 /***********************************************************************\r
12963   <<< (ClassID_SuperClass) >>> \r
12964 ************************************************************************/\r
12965 \r
12966 /*[g_ClassID_SuperClass_ID]*/\r
12967 const ClassID_Class  g_ClassID_SuperClass_ID = {\r
12968         "ClassID_SuperClass",          /* /ClassName */\r
12969         NULL,                          /* .SuperClassID_Array */\r
12970         0,                             /* .SuperClassID_Array_Count */\r
12971         sizeof( ClassID_SuperClass ),  /* .Size */\r
12972         NULL,                          /* .InitializeFunction */\r
12973         NULL,                          /* .InterfaceToVTable_Array */\r
12974         0                              /* .InterfaceToVTable_Array_Conut */\r
12975 };\r
12976 \r
12977 \r
12978  \r
12979 /***********************************************************************\r
12980   <<< (g_FinalizerInterface_ID) >>> \r
12981 ************************************************************************/\r
12982 \r
12983 const InterfaceID_Class  g_FinalizerInterface_ID = { "FinalizerInterface" };\r
12984 \r
12985 \r
12986  \r
12987 /***********************************************************************\r
12988   <<< (g_PrintXML_Interface_ID) >>> \r
12989 ************************************************************************/\r
12990 \r
12991 const InterfaceID_Class  g_PrintXML_Interface_ID = { "PrintXML_Interface" };\r
12992 \r
12993 \r
12994  \r
12995 /***********************************************************************\r
12996   <<< [malloc_redirected] >>> \r
12997 ************************************************************************/\r
12998 #undef  malloc\r
12999 void*  malloc_redirected( size_t  in_Size )\r
13000 {\r
13001         void*  address = malloc( in_Size );\r
13002 \r
13003  \r
13004         HeapLogClass_log( address, in_Size );  /*(HeapLogClass_log in malloc_redirected)*/\r
13005                 /* \8fã\8bL malloc \82Æ\82Í\95Ê\82É\81A\82±\82±\82Ì\93à\95\94\82Å realloc \82·\82é\82±\82Æ\82ª\82 \82è\82Ü\82·\81B */\r
13006 \r
13007  \r
13008         return  address;\r
13009 } /*(end_of_malloc_redirected)*/\r
13010 #define  malloc  malloc_redirected\r
13011 \r
13012 \r
13013  \r
13014 /***********************************************************************\r
13015   <<< [realloc_redirected] >>> \r
13016 ************************************************************************/\r
13017 #undef  realloc\r
13018 void*  realloc_redirected( void*  in_Address,  size_t  in_Size )\r
13019 {\r
13020         void*  address = realloc( in_Address, in_Size );\r
13021 \r
13022  \r
13023         HeapLogClass_log( address, in_Size );  /*(HeapLogClass_log in realloc_redirected)*/\r
13024                 /* \8fã\8bL realloc \82Æ\82Í\95Ê\82É\81A\82±\82±\82Ì\93à\95\94\82Å realloc \82·\82é\82±\82Æ\82ª\82 \82è\82Ü\82·\81B */\r
13025 \r
13026  \r
13027         return  address;\r
13028 } /*(end_of_realloc_redirected)*/\r
13029 #define  realloc  realloc_redirected\r
13030 \r
13031 \r
13032  \r
13033 /***********************************************************************\r
13034   <<< [calloc_redirected] >>> \r
13035 ************************************************************************/\r
13036 #undef  calloc\r
13037 void*  calloc_redirected( size_t  in_Count,  size_t  in_Size )\r
13038 {\r
13039         void*  address = calloc( in_Count, in_Size );\r
13040  \r
13041         HeapLogClass_log( address, in_Size );  /*(HeapLogClass_log in calloc_redirected)*/\r
13042  \r
13043         return  address;\r
13044 } /*(end_of_calloc_redirected)*/\r
13045 #define  calloc  calloc_redirected\r
13046 \r
13047 \r
13048  \r
13049 /***********************************************************************\r
13050   <<< [malloc_no_redirected] >>> \r
13051 ************************************************************************/\r
13052 #undef  malloc\r
13053 void*  malloc_no_redirected( size_t  in_Size )\r
13054 {\r
13055         return  malloc( in_Size );\r
13056 }\r
13057 #define  malloc  malloc_redirected\r
13058 \r
13059 \r
13060  \r
13061 /***********************************************************************\r
13062   <<< [realloc_no_redirected] >>> \r
13063 ************************************************************************/\r
13064 #undef  realloc\r
13065 void*  realloc_no_redirected( void*  in_Address,  size_t  in_Size )\r
13066 {\r
13067         return  realloc( in_Address, in_Size );\r
13068 }\r
13069 #define  realloc  realloc_redirected\r
13070 \r
13071 \r
13072  \r
13073 /***********************************************************************\r
13074   <<< [calloc_no_redirected] >>> \r
13075 ************************************************************************/\r
13076 #undef  calloc\r
13077 void*  calloc_no_redirected( size_t  in_Count,  size_t  in_Size )\r
13078 {\r
13079         return  calloc( in_Count, in_Size );\r
13080 }\r
13081 #define  calloc  calloc_redirected\r
13082 \r
13083 \r
13084  \r