OSDN Git Service

stop using trunk or dist directory in rec10 project.
[rec10/rec10-git.git] / tstools / epgdump / epgdump.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <getopt.h>
6 #include <iconv.h>
7 #include <time.h>
8
9 #include "ts.h"
10 #include "psi.h"
11 #include "sdt.h"
12 #include "sdtt.h"
13 #include "eit.h"
14 #include "tot.h"
15 #include "dsmcc.h"
16 #include "ts_ctl.h"
17 #include "util.h"
18
19 typedef         struct  _ContentTYPE{
20         char    *japanese ;
21         char    *english ;
22 }CONTENT_TYPE;
23
24 #define         CAT_COUNT               16
25 static  CONTENT_TYPE    ContentCatList[CAT_COUNT] = {
26         { "ニュース・報道", "news" },
27         { "スポーツ", "sports" },
28         { "情報", "information" },
29         { "ドラマ", "drama" },
30         { "音楽", "music" },
31         { "バラエティ", "variety" },
32         { "映画", "cinema" },
33         { "アニメ・特撮", "anime" },
34         { "ドキュメンタリー・教養", "documentary" },
35         { "演劇", "stage" },
36         { "趣味・実用", "hobby" },
37         { "福祉", "welfare" },
38         { "予備", "etc" },
39         { "予備", "etc" },
40         { "予備", "etc" },
41         { "その他", "etc" }
42 };
43
44
45 SVT_CONTROL     *svttop = NULL;
46 DSM_CONTROL     dsmctl[1024];
47 #define         SECCOUNT        64
48 static unsigned char *base64 = (unsigned char *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
49
50 static void base64_char(unsigned long bb, int srclen, unsigned char *dest, int j)
51 {
52         int x, i, base;
53
54         /* 最終位置の計算 */
55         for ( i = srclen; i < 2; i++ ) 
56                 bb <<= 8;
57
58         /* BASE64変換 */
59         for ( base = 18, x = 0; x < srclen + 2; x++, base -= 6) {
60                 dest[j++] = base64[ (unsigned long)((bb>>base) & 0x3F) ];
61         }
62
63         /* 端数の判断 */
64         for ( i = x; i < 4; i++ ) {
65                 dest[j++] = (unsigned char)'=';         /* 端数 */
66         }
67         
68 }
69
70 static void base64_encode(unsigned char *dest, const unsigned char *src, int len)
71 {
72         unsigned char *p = src;
73         unsigned long bb = (unsigned long)0;
74         int i = 0, j = 0;
75
76         while (len--)
77         {
78                 bb <<= 8;
79                 bb |= (unsigned long)*p;
80
81                 /* 24bit単位に編集 */
82                 if (i == 2) {
83                         base64_char(bb, i, dest, j);
84
85                         j = j + 4;
86                         i = 0;
87                         bb = 0;
88                 } else
89                         i++;
90
91                 p++;
92         }
93
94         /* 24bitに満たない場合 */
95         if (i) base64_char(bb, i - 1, dest, j);
96
97 }
98
99 void    xmlspecialchars(char *str)
100 {
101         strrep(str, "&", "&amp;");
102         strrep(str, "'", "&apos;");
103         strrep(str, "\"", "&quot;");
104         strrep(str, "<", "&lt;");
105         strrep(str, ">", "&gt;");
106 }
107
108
109
110 void    GetSDT(FILE *infile, SVT_CONTROL *svttop, SECcache *secs, 
111         int count, STATION **station, int * station_count, char *header, int is_logo)
112 {
113         SECcache  *bsecs;
114         int pmtpids[SECCOUNT];
115         memset(pmtpids, 0, sizeof(pmtpids));
116         int dsmccpids[SECCOUNT];
117         memset(dsmccpids, 0, sizeof(dsmccpids));
118         int i = 0 , downloadDataId = 0;
119
120         while((bsecs = readTS(infile, secs, count)) != NULL) {
121                 /* SDT */
122                 if((bsecs->pid & 0xFF) == 0x11) {
123                         dumpSDT(bsecs->buf, svttop, station, station_count, header);
124                 }
125                 /* TOT */
126                 else if((bsecs->pid & 0xFF) == 0x14) {
127                         dumpTOT(bsecs->buf);
128                 }
129                 /* SDTT */
130                 //else if((bsecs->pid & 0xFF) == 0x23) {
131                 //      dumpSDTT(bsecs->buf, *station, *station_count);
132                 //}
133                 /* BIT */
134                 else if((bsecs->pid & 0xFF) == 0x24) {
135                         dumpBIT(bsecs->buf);
136                 }
137                 /* CDT */
138                 else if((bsecs->pid & 0xFF) == 0x29) {
139                         dumpCDT(bsecs->buf, *station, *station_count);
140                 }
141                 else if ( is_logo ) {
142                         /* PAT */
143                         if((bsecs->pid & 0xFF) == 0x00) {
144                                 dumpPAT(bsecs->buf, secs, count, pmtpids);
145                         }
146                         /* PMT */
147                         for ( i = 1; i < SECCOUNT; i++ ) {
148                                 if ( pmtpids[i] == 0 ) {
149                                         break;
150                                 }
151                                 /* PMT specified by PAT */
152                                 if ( bsecs->pid == pmtpids[i] ) {
153                                         dumpPMT(bsecs->buf, secs, count, dsmccpids);
154                                 }
155                         }
156                         /* DSM-CC */
157                         for ( i = 0; i < SECCOUNT; i++ ) {
158                                 if ( dsmccpids[i] == 0 ) {
159                                         break;
160                                 }
161                                 /* DSM-CC specified by PMT */
162                                 if ( bsecs->pid == dsmccpids[i] ) {
163                                         dumpDSMCC(bsecs->buf, &downloadDataId, &dsmctl);
164                                 }
165                         }
166                 }
167         }
168 }
169
170 void    GetEIT(FILE *infile, FILE *outfile, STATION *psta, SECcache *secs)
171 {
172         SECcache  *bsecs;
173         EIT_CONTROL     *eitcur ;
174         EIT_CONTROL     *eitnext ;
175         EIT_CONTROL     *eittop = NULL;
176         time_t  l_time ;
177         time_t  end_time ;
178         struct  tm      tl ;
179         struct  tm      *endtl ;
180         char    cendtime[32];
181         char    cstarttime[32];
182
183         char    title[1024];
184         char    subtitle[1024];
185         char    desc[102400] = {0};
186         char    Category[1024];
187         char    VideoType[1024];
188         char    AudioType[1024];
189
190         memset(secs, 0,  sizeof(SECcache) * SECCOUNT);
191         secs[0].pid = 0x12; /* EIT  */
192         secs[1].pid = 0x26; /* EIT  */
193         secs[2].pid = 0x27; /* EIT  */
194
195         eittop = calloc(1, sizeof(EIT_CONTROL));
196         eitcur = eittop ;
197         fseek(infile, 0, SEEK_SET);
198         while((bsecs = readTS(infile, secs, SECCOUNT)) != NULL) {
199                 /* EIT */
200                 if((bsecs->pid & 0xFF) == 0x12) {
201                         dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
202                 }else if((bsecs->pid & 0xFF) == 0x26) {
203                         dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
204                 }else if((bsecs->pid & 0xFF) == 0x27) {
205                         dumpEIT(bsecs->buf, psta->svId, psta->onId, psta->tsId, eittop);
206                 }
207         }
208         eitcur = eittop ;
209         while(eitcur != NULL){
210                 if(!eitcur->servid){
211                         eitcur = eitcur->next ;
212                         continue ;
213                 }
214                 if(eitcur->content_type > CAT_COUNT){
215                         eitcur->content_type = CAT_COUNT -1 ;
216                 }
217                 memset(title, '\0', sizeof(title));
218                 strcpy(title, eitcur->title);
219                 xmlspecialchars(title);
220
221                 memset(subtitle, '\0', sizeof(subtitle));
222                 strcpy(subtitle, eitcur->subtitle);
223                 xmlspecialchars(subtitle);
224
225                 memset(desc, '\0', sizeof(desc));
226                 if ( eitcur->desc ) {
227                         strcpy(desc, eitcur->desc);
228                         xmlspecialchars(desc);
229                 }
230
231                 memset(Category, '\0', sizeof(Category));
232                 strcpy(Category, ContentCatList[eitcur->content_type].japanese);
233                 xmlspecialchars(Category);
234
235                 memset(VideoType, '\0', sizeof(VideoType));
236                 strcpy(VideoType, parseComponentDescType(eitcur->video_type));
237                 xmlspecialchars(VideoType);
238
239                 memset(AudioType, '\0', sizeof(AudioType));
240                 strcpy(AudioType, parseAudioComponentDescType(eitcur->audio_type));
241                 xmlspecialchars(AudioType);
242
243                 tl.tm_sec = eitcur->ss ;
244                 tl.tm_min = eitcur->hm ;
245                 tl.tm_hour = eitcur->hh ;
246                 tl.tm_mday = eitcur->dd ;
247                 tl.tm_mon = (eitcur->mm - 1);
248                 tl.tm_year = (eitcur->yy - 1900);
249                 tl.tm_wday = 0;
250                 tl.tm_isdst = 0;
251                 tl.tm_yday = 0;
252                 l_time = mktime(&tl);
253                 if((eitcur->ehh == 0) && (eitcur->emm == 0) && (eitcur->ess == 0)){
254                         (void)time(&l_time);
255                         end_time = l_time + (60 * 5);           // 5分後に設定
256                 endtl = localtime(&end_time);
257                 }else{
258                         end_time = l_time + eitcur->ehh * 3600 + eitcur->emm * 60 + eitcur->ess;
259                         endtl = localtime(&end_time);
260                 }
261                 memset(cendtime, '\0', sizeof(cendtime));
262                 memset(cstarttime, '\0', sizeof(cstarttime));
263                 strftime(cendtime, (sizeof(cendtime) - 1), "%Y%m%d%H%M%S", endtl);
264                 strftime(cstarttime, (sizeof(cstarttime) - 1), "%Y%m%d%H%M%S", &tl);
265
266                 fprintf(outfile, "  <programme start=\"%s +0900\" stop=\"%s +0900\" channel=\"%s\" event=\"%d\">\n",    
267                                 cstarttime, cendtime, psta->ontv, eitcur->event_id);
268                 fprintf(outfile, "    <title lang=\"ja_JP\">%s</title>\n", title);
269                 fprintf(outfile, "    <desc lang=\"ja_JP\">%s</desc>\n", subtitle);
270                 fprintf(outfile, "    <longdesc lang=\"ja_JP\">%s</longdesc>\n", desc);
271                 fprintf(outfile, "    <category lang=\"ja_JP\">%s</category>\n", Category);
272                 fprintf(outfile, "    <video type=\"%d\">%s</video>\n", eitcur->video_type, VideoType);
273                 fprintf(outfile, "    <audio type=\"%d\" multi=\"%d\">%s</audio>\n", eitcur->audio_type, eitcur->multi_type, AudioType);
274                 //fprintf(outfile, "    <category lang=\"en\">%s</category>\n", ContentCatList[eitcur->content_type].english);
275                 fprintf(outfile, "  </programme>\n");
276 #if 0
277                 fprintf(outfile, "(%x:%x:%x)%s,%s,%s,%s,%s,%s\n",
278                                         eitcur->servid, eitcur->table_id, eitcur->event_id,
279                                         cstarttime, cendtime,
280                                         title, subtitle,
281                                         Category,
282                                         ContentCatList[eitcur->content_type].english);
283
284                 fprintf(outfile, "(%x:%x)%04d/%02d/%02d,%02d:%02d:%02d,%02d:%02d:%02d,%s,%s,%s,%s\n",
285                                         eitcur->table_id, eitcur->event_id,
286                                         eitcur->yy, eitcur->mm, eitcur->dd,
287                                         eitcur->hh, eitcur->hm, eitcur->ss,
288                                         eitcur->ehh, eitcur->emm, eitcur->ess,
289                                         eitcur->title, eitcur->subtitle,
290                                         ContentCatList[eitcur->content_type].japanese,
291                                         ContentCatList[eitcur->content_type].english);
292 #endif
293                 eitnext = eitcur->next ;
294                 free(eitcur->title);
295                 free(eitcur->subtitle);
296                 free(eitcur);
297                 eitcur = eitnext ;
298         }
299         free(eittop);
300         eittop = NULL;
301 }
302
303 void checkSta(STATION **station,int *stalength){
304         STATION *statmp;
305         int chl[90];
306         int chlt = 0;
307         int stal = 0;
308         STATION * statin = *station;
309         statmp = malloc( sizeof(STATION) * 2 );
310         for (int i = 0 ; i < *stalength ; i++){
311                 int noidinchl = 1;
312                 for (int j = 0 ; j < chlt ; j++){
313                         if ( chl[j] == statin[i].svId ) {
314                                 noidinchl = 0;
315                         }
316                 }
317                 if ( noidinchl == 1 ) {
318                         statmp = realloc(statmp, (stal+1) * sizeof(STATION));
319                         statmp[stal] = statin[i];
320                         chl[chlt] = statin[i].svId;
321                         chlt++;
322                         stal++;
323                 }
324         }
325         *station = statmp;
326         *stalength = stal;//ここいらが怪しい
327         //memcpy(statin,statmp,chlt*sizeof(STATION));
328         //free(statmp);
329         return;
330 }
331
332 int main(int argc, char *argv[])
333 {
334
335         FILE *infile = stdin;
336         FILE *outfile = stdout;
337         char    *arg_onTV ;
338         int             staCount ;
339         int   inclose = 0;
340         int   outclose = 0;
341         SVT_CONTROL     *svtcur ;
342         SVT_CONTROL     *svtsave ;
343         SECcache   secs[SECCOUNT];
344         int             lp ;
345         STATION *pStas ;
346         int             act = 0;
347         int             i , j, k ;
348         int             is_logo = 0;
349         SDTTdata  sdtd;
350         SDTTdataLoop *loop;
351         SDTTdataService *service;
352
353         memset(dsmctl, 0,  sizeof(dsmctl));
354
355         if(argc == 5 && strcmp(argv[1], "/LOGO") == 0){
356                 argc--;
357                 argv[1] = argv[2];
358                 argv[2] = argv[3];
359                 argv[3] = argv[4];
360                 is_logo = 1;
361         }
362         if(argc == 4){
363                 arg_onTV = argv[1];
364                 if(strcmp(argv[2], "-")) {
365                         infile = fopen(argv[2], "r");
366                         if ( !infile) {
367                           printf( "tsFile not found (Can't open file: %s)\n", argv[2] );
368                           exit( -1 );
369                         }
370                         inclose = 1;
371                 }
372                 else {
373                         infile = stdin;
374                 }
375                 if(strcmp(argv[3], "-")) {
376                         outfile = fopen(argv[3], "w+");
377                         if ( !outfile) {
378                           printf( "xmlFile not found (Can't open file: %s)\n", argv[3] );
379                           exit( -1 );
380                         }
381                         outclose = 1;
382                 }
383                 else {
384                         outfile = stdout;
385                 }
386         }else{
387                 fprintf(stdout, "Usage : %s (/LOGO) {/BS|/CS|<id>} <tsFile> <outfile>\n", argv[0]);
388                 fprintf(stdout, "\n");
389                 fprintf(stdout, "/LOGO    ロゴ取得モード。独立して指定し、番組表の出力を行ないません。\n");
390                 fprintf(stdout, "         必要なTSの長さ 地上波は10分 BS/CSは20分です。\n");
391                 fprintf(stdout, "id       チャンネル識別子。地上波の物理チャンネルを与えます。\n");
392                 fprintf(stdout, "/BS      BSモード。一つのTSからBS全局のデータを読み込みます。\n");
393                 fprintf(stdout, "/CS      CSモード。一つのTSから複数局のデータを読み込みます。\n");
394                 fprintf(stdout, "/TIME    時刻合わせモード。TSからTOT(Time Offset Table)を読み込みます。\n");
395                 fprintf(stdout, "         recpt1 <任意> 10(秒以上) - | epgdump /TIME - <任意>の形で使用してください。\n");
396                 fprintf(stdout, "         TOTは5秒に1回しか来ないため、recpt1に与える時間をある程度長くしてください。\n");
397 /*
398                 fprintf(stdout, "  ontvcode   Channel identifier (ex. ****.ontvjapan.com)\n");
399                 fprintf(stdout, "  /BS        BS mode\n");
400                 fprintf(stdout, "               This mode reads the data of all BS TV stations\n");
401                 fprintf(stdout, "               from one TS data.\n");
402                 fprintf(stdout, "  /CS        CS mode\n");
403                 fprintf(stdout, "               This mode reads the data of two or more CS TV stations\n");
404                 fprintf(stdout, "               from one TS data.\n");
405 */
406                 return 0;
407         }
408
409         pStas = NULL;
410         staCount = 0;
411         svttop = calloc(1, sizeof(SVT_CONTROL));
412         act = 0 ;
413
414         /* 興味のあるpidを指定 */
415         if ( is_logo ) {
416                 memset(secs, 0,  sizeof(SECcache) * SECCOUNT);
417                 secs[0].pid = 0x00; /* PAT  */
418                 secs[1].pid = 0x11; /* SDT  */
419                 secs[2].pid = 0x29; /* CDT  */
420         }
421         else {
422                 memset(secs, 0,  sizeof(SECcache) * SECCOUNT);
423                 secs[0].pid = 0x00; /* PAT  */
424                 secs[1].pid = 0x11; /* SDT  */
425                 secs[2].pid = 0x12; /* EIT  */
426                 secs[3].pid = 0x23; /* SDTT */
427                 secs[4].pid = 0x26; /* EIT  */
428                 secs[5].pid = 0x27; /* EIT  */
429                 secs[6].pid = 0x29; /* CDT  */
430         }
431
432         if(strcmp(arg_onTV, "/TIME") == 0){
433                 printf("TSに載っている時刻データは2秒ほど早めてあるのかもしれません。\n");
434                 memset(secs, 0,  sizeof(SECcache) * SECCOUNT);
435                 secs[0].pid = 0x14; /* TOT  */
436
437                 GetSDT(infile, NULL, secs, SECCOUNT,NULL, NULL,NULL, 0);
438
439                 goto cleanup;
440         }else if(strcmp(arg_onTV, "/BS") == 0){
441                 char *head = "BS";
442                 GetSDT(infile, svttop, secs, SECCOUNT, &pStas, &staCount, head, is_logo);
443         }else if(strcmp(arg_onTV, "/CS") == 0){
444                 char *head = "CS";
445                 GetSDT(infile, svttop, secs, SECCOUNT, &pStas, &staCount, head, is_logo);
446         }else if(strcmp(arg_onTV, "/TEST") == 0){
447                 memset(secs, 0,  sizeof(SECcache) * SECCOUNT);
448                 secs[0].pid = 0x24; /* BIT  */
449
450                 char *head = "TEST";
451                 GetSDT(infile, svttop, secs, SECCOUNT, &pStas, &staCount, head, 0);
452                 //if (sta_count) 
453                 //      printf("Station count: %d\n1st ontv=%s,name=%s\n",staCount, pStas[0].ontv, pStas[0].name);
454         }else{
455                 GetSDT(infile, svttop, secs, SECCOUNT, &pStas, &staCount, arg_onTV, 0);
456
457                 // 地上波のマルチチャンネル対応のためコメントアウト
458                 /*
459                 act = 1 ;
460                 svttop = calloc(1, sizeof(SVT_CONTROL));
461                 GetSDT(infile, svttop, secs, SECCOUNT);
462                 svtcur = svttop->next ; //先頭
463                 if(svtcur == NULL){
464                         free(svttop);
465                         return 1;
466                 }
467
468                 pStas = calloc(1, sizeof(STATION));
469                 pStas->tsId = svtcur->transport_stream_id ;
470                 pStas->onId = svtcur->original_network_id ;
471                 pStas->svId = svtcur->event_id ;
472                 pStas->ontv = arg_onTV ;
473                 pStas->name = svtcur->servicename ;
474                 staCount = 1;
475                 */
476         }
477         checkSta(&pStas, &staCount);
478
479         fprintf(outfile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
480         fprintf(outfile, "<!DOCTYPE tv SYSTEM \"xmltv.dtd\">\n\n");
481         fprintf(outfile, "<tv generator-info-name=\"tsEPG2xml\" generator-info-url=\"http://localhost/\">\n");
482
483         char    ServiceName[1024];
484         char    Logo[8192];
485
486         if ( is_logo ) {
487                 memset(Logo, '\0', sizeof(Logo));
488                 for(lp = 0 ; lp < staCount ; lp++){
489                         for ( i = 0 ; i < 6 ; i++) {
490                                 if (pStas[lp].logo_array[i].logo) {
491                                         base64_encode(Logo, pStas[lp].logo_array[i].logo, pStas[lp].logo_array[i].logo_size);
492                                         xmlspecialchars(Logo);
493                                         fprintf(outfile, "    <logo ts=\"%d\" on=\"%d\" sv=\"%d\" type=\"%d\">%s</logo>\n", 
494                                                 pStas[lp].tsId, 
495                                                 pStas[lp].onId, 
496                                                 pStas[lp].svId, 
497                                                 i, 
498                                                 Logo);
499                                 }
500                         }
501                 }
502
503                 for ( i = 0; i < 1024; i++) {
504                         if ( dsmctl[i].isUsed == 0 ) break;
505                         parseSDTTdata(dsmctl[i].blockData, &sdtd);
506
507                         for (j = 0; j < sdtd.number_of_loop; j++) {
508                                 loop = sdtd.loop + sizeof(SDTTdataLoop) * j;
509
510                                 for ( k = 0; k < loop->number_of_services; k++) {
511                                         service = loop->services + sizeof(SDTTdataService) * k;
512
513                                         /*
514                                         for(lp = 0 ; lp < staCount ; lp++){
515                                                 if ( 
516                                                         pStas[lp].tsId == service->transport_stream_id && 
517                                                         pStas[lp].onId == service->original_network_id && 
518                                                         pStas[lp].svId == service->service_id
519                                                 ) {
520                                                         clt2png(loop->data, 
521                                                                 &pStas[lp].logo_array[sdtd.logo_type].logo, 
522                                                                 &pStas[lp].logo_array[sdtd.logo_type].logo_size);
523                                                 }
524                                         }
525                                         */
526
527                                         #if 0
528                                         printf( "SDTTdataLoop (%d:%d) %d:%d[%d:%d:%d]%d\n", 
529                                                 i, j, 
530                                                 sdtd.logo_type, 
531                                                 loop->logo_id, 
532                                                 service->transport_stream_id, 
533                                                 service->original_network_id, 
534                                                 service->service_id, 
535                                                 loop->data_size
536                                         );
537                                         #endif
538
539                                 
540                                         void* logo = NULL;
541                                         int logo_size = 0;
542
543                                         clt2png(loop->data, &logo, &logo_size);
544                                         memset(Logo, '\0', sizeof(Logo));
545                                         base64_encode(Logo, logo, logo_size);
546                                         xmlspecialchars(Logo);
547
548                                         fprintf(outfile, "  <logo ts=\"%d\" on=\"%d\" sv=\"%d\" type=\"%d\" dlid=\"%d\">%s</logo>\n", 
549                                                 service->transport_stream_id, 
550                                                 service->original_network_id, 
551                                                 service->service_id, 
552                                                 sdtd.logo_type, 
553                                                 loop->logo_id, 
554                                                 Logo);
555                                 }
556
557                         }
558                 }
559         }
560         for(lp = 0 ; lp < staCount ; lp++){
561                 memset(ServiceName, '\0', sizeof(ServiceName));
562                 strcpy(ServiceName, pStas[lp].name);
563                 xmlspecialchars(ServiceName);
564
565                 fprintf(outfile, "  <channel id=\"%s\">\n", pStas[lp].ontv);
566                 fprintf(outfile, "    <display-name lang=\"ja_JP\">%s</display-name>\n", ServiceName);
567                 fprintf(outfile, "    <id ts=\"%d\" on=\"%d\" sv=\"%d\"/>\n", pStas[lp].tsId, pStas[lp].onId, pStas[lp].svId);
568
569                 fprintf(outfile, "  </channel>\n");
570         }
571         if ( is_logo ) {
572                 fprintf(outfile, "</tv>\n");
573                 goto cleanup;
574         }
575         for(lp = 0 ; lp < staCount ; lp++){
576                 GetEIT(infile, outfile, &pStas[lp], secs);
577         }
578         fprintf(outfile, "</tv>\n");
579 cleanup: 
580         if(inclose) {
581                 fclose(infile);
582         }
583         if(outclose) {
584                 fclose(outfile);
585         }
586         if(act){
587                 free(pStas);
588                 svtcur = svttop ;       //先頭
589                 while(svtcur != NULL){
590                         svtsave = svtcur->next ;
591                         free(svtcur);
592                         svtcur = svtsave ;
593                 }
594         }
595
596         return 0;
597 }
598