Reformat
[yaz-moved-to-github.git] / src / ill-get.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file ill-get.c
7  * \brief Implements ILL package creator utilities
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <stdlib.h>
14 #include <yaz/ill.h>
15
16 bool_t *ill_get_bool(struct ill_get_ctl *gc, const char *name,
17                      const char *sub, int val)
18 {
19     ODR o = gc->odr;
20     char element[128];
21     const char *v;
22     bool_t *r = (bool_t *) odr_malloc(o, sizeof(*r));
23     
24     strcpy(element, name);
25     if (sub)
26     {
27         strcat(element, ",");
28         strcat(element, sub);
29     }    
30
31     v = (gc->f)(gc->clientData, element);
32     if (v)
33         val = atoi(v);
34     else if (val < 0)
35         return 0;
36     *r = val;
37     return r;
38 }
39
40 Odr_int *ill_get_int(struct ill_get_ctl *gc, const char *name,
41                      const char *sub, Odr_int val)
42 {
43     ODR o = gc->odr;
44     char element[128];
45     const char *v;
46     
47     strcpy(element, name);
48     if (sub)
49     {
50         strcat(element, ",");
51         strcat(element, sub);
52     }    
53     v = (gc->f)(gc->clientData, element);
54     if (v)
55         val = atoi(v);
56     return odr_intdup(o, val);
57 }
58
59 Odr_int *ill_get_enumerated(struct ill_get_ctl *gc, const char *name,
60                             const char *sub, Odr_int val)
61 {
62     return ill_get_int(gc, name, sub, val);
63 }
64
65 ILL_String *ill_get_ILL_String_x(struct ill_get_ctl *gc, const char *name,
66                                  const char *sub, const char *vdefault)
67 {
68     ILL_String *r = (ILL_String *) odr_malloc(gc->odr, sizeof(*r));
69     char element[128];
70     const char *v;
71
72     strcpy(element, name);
73     if (sub)
74     {
75         strcat(element, ",");
76         strcat(element, sub);
77     }
78     v = (gc->f)(gc->clientData, element);
79     if (!v)
80         v = vdefault;
81     if (!v)
82         return 0;
83     r->which = ILL_String_GeneralString;
84     r->u.GeneralString = odr_strdup(gc->odr, v);
85     return r;
86 }
87
88 ILL_String *ill_get_ILL_String(struct ill_get_ctl *gc, const char *name,
89                                const char *sub)
90 {
91     return ill_get_ILL_String_x(gc, name, sub, 0);
92 }
93
94 ILL_ISO_Date *ill_get_ILL_ISO_Date(struct ill_get_ctl *gc, const char *name,
95                                    const char *sub, const char *val)
96 {
97     char element[128];
98     const char *v;
99
100     strcpy(element, name);
101     if (sub)
102     {
103         strcat(element, ",");
104         strcat(element, sub);
105     }
106     v = (gc->f)(gc->clientData, element);
107     if (!v)
108         v = val;
109     if (!v)
110         return 0;
111     return odr_strdup(gc->odr, v);
112 }
113
114 ILL_ISO_Time *ill_get_ILL_ISO_Time(struct ill_get_ctl *gc, const char *name,
115                                    const char *sub, const char *val)
116 {
117     char element[128];
118     const char *v;
119
120     strcpy(element, name);
121     if (sub)
122     {
123         strcat(element, ",");
124         strcat(element, sub);
125     }
126     v = (gc->f)(gc->clientData, element);
127     if (!v)
128         v = val;
129     if (!v)
130         return 0;
131     return odr_strdup(gc->odr, v);
132 }
133
134 ILL_Person_Or_Institution_Symbol *ill_get_Person_Or_Insitution_Symbol(
135     struct ill_get_ctl *gc, const char *name, const char *sub)
136 {
137     char element[128];
138     ODR o = gc->odr;
139     ILL_Person_Or_Institution_Symbol *p =
140         (ILL_Person_Or_Institution_Symbol *) odr_malloc(o, sizeof(*p));
141     
142     strcpy(element, name);
143     if (sub)
144     {
145         strcat(element, ",");
146         strcat(element, sub);
147     }
148     p->which = ILL_Person_Or_Institution_Symbol_person_symbol;
149     if ((p->u.person_symbol = ill_get_ILL_String(gc, element, "person")))
150         return p;
151
152     p->which = ILL_Person_Or_Institution_Symbol_institution_symbol;
153     if ((p->u.institution_symbol =
154          ill_get_ILL_String(gc, element, "institution")))
155         return p;
156     return 0;
157 }
158
159 static ILL_Name_Of_Person_Or_Institution *ill_get_Name_Of_Person_Or_Institution(
160     struct ill_get_ctl *gc, const char *name, const char *sub)
161 {
162     char element[128];
163     ODR o = gc->odr;
164     ILL_Name_Of_Person_Or_Institution *p =
165         (ILL_Name_Of_Person_Or_Institution *) odr_malloc(o, sizeof(*p));
166     
167     strcpy(element, name);
168     if (sub)
169     {
170         strcat(element, ",");
171         strcat(element, sub);
172     }
173     p->which = ILL_Name_Of_Person_Or_Institution_name_of_person;
174     if ((p->u.name_of_person =
175          ill_get_ILL_String(gc, element, "name-of-person")))
176         return p;
177
178     p->which = ILL_Name_Of_Person_Or_Institution_name_of_institution;
179     if ((p->u.name_of_institution =
180          ill_get_ILL_String(gc, element, "name-of-institution")))
181         return p;
182     return 0;
183 }
184     
185 ILL_System_Id *ill_get_System_Id(struct ill_get_ctl *gc,
186                                  const char *name, const char *sub)
187 {
188     ODR o = gc->odr;
189     char element[128];
190     ILL_System_Id *p;
191     
192     strcpy(element, name);
193     if (sub)
194     {
195         strcat(element, ",");
196         strcat(element, sub);
197     }
198     p = (ILL_System_Id *) odr_malloc(o, sizeof(*p));
199     p->person_or_institution_symbol = ill_get_Person_Or_Insitution_Symbol(
200         gc, element, "person-or-institution-symbol");
201     p->name_of_person_or_institution = ill_get_Name_Of_Person_Or_Institution(
202         gc, element, "name-of-person-or-institution");
203     return p;
204 }
205
206 ILL_Transaction_Id *ill_get_Transaction_Id(struct ill_get_ctl *gc,
207                                            const char *name, const char *sub)
208 {
209     ODR o = gc->odr;
210     ILL_Transaction_Id *r = (ILL_Transaction_Id *) odr_malloc(o, sizeof(*r));
211     char element[128];
212     
213     strcpy(element, name);
214     if (sub)
215     {
216         strcat(element, ",");
217         strcat(element, sub);
218     }    
219     r->initial_requester_id =
220         ill_get_System_Id(gc, element, "initial-requester-id");
221     r->transaction_group_qualifier =
222         ill_get_ILL_String_x(gc, element, "transaction-group-qualifier", "");
223     r->transaction_qualifier =
224         ill_get_ILL_String_x(gc, element, "transaction-qualifier", "");
225     r->sub_transaction_qualifier =
226         ill_get_ILL_String(gc, element, "sub-transaction-qualifier");
227     return r;
228 }
229
230
231 ILL_Service_Date_this *ill_get_Service_Date_this(
232     struct ill_get_ctl *gc, const char *name, const char *sub)
233 {
234     ODR o = gc->odr;
235     ILL_Service_Date_this *r =
236         (ILL_Service_Date_this *) odr_malloc(o, sizeof(*r));
237     char element[128];
238     
239     strcpy(element, name);
240     if (sub)
241     {
242         strcat(element, ",");
243         strcat(element, sub);
244     }
245     r->date = ill_get_ILL_ISO_Date(gc, element, "date", "20000101");
246     r->time = ill_get_ILL_ISO_Time(gc, element, "time", 0);
247     return r;
248 }
249
250 ILL_Service_Date_original *ill_get_Service_Date_original(
251     struct ill_get_ctl *gc, const char *name, const char *sub)
252 {
253     ODR o = gc->odr;
254     ILL_Service_Date_original *r =
255         (ILL_Service_Date_original *) odr_malloc(o, sizeof(*r));
256     char element[128];
257     
258     strcpy(element, name);
259     if (sub)
260     {
261         strcat(element, ",");
262         strcat(element, sub);
263     }
264     r->date = ill_get_ILL_ISO_Date(gc, element, "date", 0);
265     r->time = ill_get_ILL_ISO_Time(gc, element, "time", 0);
266     if (!r->date && !r->time)
267         return 0;
268     return r;
269 }
270
271 ILL_Service_Date_Time *ill_get_Service_Date_Time(
272     struct ill_get_ctl *gc, const char *name, const char *sub)
273 {
274     ODR o = gc->odr;
275     ILL_Service_Date_Time *r =
276         (ILL_Service_Date_Time *) odr_malloc(o, sizeof(*r));
277     char element[128];
278     
279     strcpy(element, name);
280     if (sub)
281     {
282         strcat(element, ",");
283         strcat(element, sub);
284     }    
285     r->date_time_of_this_service = ill_get_Service_Date_this(
286         gc, element, "this");
287     r->date_time_of_original_service = ill_get_Service_Date_original(
288         gc, element, "original");
289     return r;
290 }
291
292 ILL_Requester_Optional_Messages_Type *ill_get_Requester_Optional_Messages_Type(
293     struct ill_get_ctl *gc, const char *name, const char *sub)
294 {
295     ODR o = gc->odr;
296     ILL_Requester_Optional_Messages_Type *r =
297         (ILL_Requester_Optional_Messages_Type *) odr_malloc(o, sizeof(*r));
298     char element[128];
299     
300     strcpy(element, name);
301     if (sub)
302     {
303         strcat(element, ",");
304         strcat(element, sub);
305     }
306     r->can_send_RECEIVED = ill_get_bool(gc, element, "can-send-RECEIVED", 0);
307     r->can_send_RETURNED = ill_get_bool(gc, element, "can-send-RETURNED", 0);
308     r->requester_SHIPPED =
309         ill_get_enumerated(gc, element, "requester-SHIPPED", 1);
310     r->requester_CHECKED_IN =
311         ill_get_enumerated(gc, element, "requester-CHECKED-IN", 1);
312     return r;
313 }
314
315 ILL_Item_Id *ill_get_Item_Id(
316     struct ill_get_ctl *gc, const char *name, const char *sub)   
317 {
318     ODR o = gc->odr;
319     ILL_Item_Id *r = (ILL_Item_Id *) odr_malloc(o, sizeof(*r));
320     char element[128];
321     
322     strcpy(element, name);
323     if (sub)
324     {
325         strcat(element, ",");
326         strcat(element, sub);
327     }
328     r->item_type = ill_get_enumerated(gc, element, "item-type",
329                                       ILL_Item_Id_monograph);
330     r->held_medium_type = 0;
331     r->call_number = ill_get_ILL_String(gc, element, "call-number");
332     r->author = ill_get_ILL_String(gc, element, "author");
333     r->title = ill_get_ILL_String(gc, element, "title");
334     r->sub_title = ill_get_ILL_String(gc, element, "sub-title");
335     r->sponsoring_body = ill_get_ILL_String(gc, element, "sponsoring-body");
336     r->place_of_publication =
337         ill_get_ILL_String(gc, element, "place-of-publication");
338     r->publisher = ill_get_ILL_String(gc, element, "publisher");
339     r->series_title_number =
340         ill_get_ILL_String(gc, element, "series-title-number");
341     r->volume_issue = ill_get_ILL_String(gc, element, "volume-issue");
342     r->edition = ill_get_ILL_String(gc, element, "edition");
343     r->publication_date = ill_get_ILL_String(gc, element, "publication-date");
344     r->publication_date_of_component =
345         ill_get_ILL_String(gc, element, "publication-date-of-component");
346     r->author_of_article = ill_get_ILL_String(gc, element,
347                                               "author-of-article");
348     r->title_of_article = ill_get_ILL_String(gc, element, "title-of-article");
349     r->pagination = ill_get_ILL_String(gc, element, "pagination");
350     r->national_bibliography_no = 0;
351     r->iSBN = ill_get_ILL_String(gc, element, "ISBN");
352     r->iSSN = ill_get_ILL_String(gc, element, "ISSN");
353     r->system_no = 0;
354     r->additional_no_letters =
355         ill_get_ILL_String(gc, element, "additional-no-letters");
356     r->verification_reference_source = 
357         ill_get_ILL_String(gc, element, "verification-reference-source");
358     return r;
359 }
360
361
362 ILL_Client_Id *ill_get_Client_Id(
363     struct ill_get_ctl *gc, const char *name, const char *sub)
364 {
365     char element[128];
366     ODR o = gc->odr;
367     ILL_Client_Id *r = (ILL_Client_Id *) odr_malloc(o, sizeof(*r));
368
369     strcpy(element, name);
370     if (sub)
371     {
372         strcat(element, ",");
373         strcat(element, sub);
374     }
375     r->client_name = ill_get_ILL_String(gc, element, "client-name");
376     r->client_status = ill_get_ILL_String(gc, element, "client-status");
377     r->client_identifier = ill_get_ILL_String(gc, element,
378                                               "client-identifier");
379     return r;
380 }
381
382 ILL_Postal_Address *ill_get_Postal_Address(
383     struct ill_get_ctl *gc, const char *name, const char *sub)
384 {
385     ODR o = gc->odr;
386     ILL_Postal_Address *r =
387         (ILL_Postal_Address *) odr_malloc(o, sizeof(*r));
388     char element[128];
389
390     strcpy(element, name);
391     if (sub)
392     {
393         strcat(element, ",");
394         strcat(element, sub);
395     }
396     r->name_of_person_or_institution = 
397         ill_get_Name_Of_Person_Or_Institution(
398             gc, element, "name-of-person-or-institution");
399     r->extended_postal_delivery_address =
400         ill_get_ILL_String(
401             gc, element, "extended-postal-delivery-address");
402     r->street_and_number =
403         ill_get_ILL_String(gc, element, "street-and-number");
404     r->post_office_box =
405         ill_get_ILL_String(gc, element, "post-office-box");
406     r->city = ill_get_ILL_String(gc, element, "city");
407     r->region = ill_get_ILL_String(gc, element, "region");
408     r->country = ill_get_ILL_String(gc, element, "country");
409     r->postal_code = ill_get_ILL_String(gc, element, "postal-code");
410     return r;
411 }
412
413 ILL_System_Address *ill_get_System_Address(
414     struct ill_get_ctl *gc, const char *name, const char *sub)
415 {
416     ODR o = gc->odr;
417     ILL_System_Address *r =
418         (ILL_System_Address *) odr_malloc(o, sizeof(*r));
419     char element[128];
420     
421     strcpy(element, name);
422     if (sub)
423     {
424         strcat(element, ",");
425         strcat(element, sub);
426     }
427     r->telecom_service_identifier =
428         ill_get_ILL_String(gc, element, "telecom-service-identifier");
429     r->telecom_service_address =
430         ill_get_ILL_String(gc, element, "telecom-service-addreess");
431     return r;
432 }
433
434 ILL_Delivery_Address *ill_get_Delivery_Address(
435     struct ill_get_ctl *gc, const char *name, const char *sub)
436 {
437     ODR o = gc->odr;
438     ILL_Delivery_Address *r =
439         (ILL_Delivery_Address *) odr_malloc(o, sizeof(*r));
440     char element[128];
441     
442     strcpy(element, name);
443     if (sub)
444     {
445         strcat(element, ",");
446         strcat(element, sub);
447     }
448     r->postal_address =
449         ill_get_Postal_Address(gc, element, "postal-address");
450     r->electronic_address =
451         ill_get_System_Address(gc, element, "electronic-address");
452     return r;
453 }
454
455 ILL_Search_Type *ill_get_Search_Type(
456     struct ill_get_ctl *gc, const char *name, const char *sub)
457 {
458     ODR o = gc->odr;
459     ILL_Search_Type *r = (ILL_Search_Type *) odr_malloc(o, sizeof(*r));
460     char element[128];
461     
462     strcpy(element, name);
463     if (sub)
464     {
465         strcat(element, ",");
466         strcat(element, sub);
467     }
468     r->level_of_service = ill_get_ILL_String(gc, element, "level-of-service");
469     r->need_before_date = ill_get_ILL_ISO_Date(gc, element,
470                                                "need-before-date", 0);
471     r->expiry_date = ill_get_ILL_ISO_Date(gc, element, "expiry-date", 0);
472     r->expiry_flag = ill_get_enumerated(gc, element, "expiry-flag", 3);
473                                          
474     return r;
475 }
476
477 ILL_Request *ill_get_ILLRequest(
478     struct ill_get_ctl *gc, const char *name, const char *sub)
479 {
480     ODR o = gc->odr;
481     ILL_Request *r = (ILL_Request *) odr_malloc(o, sizeof(*r));
482     char element[128];
483     
484     strcpy(element, name);
485     if (sub)
486     {
487         strcat(element, ",");
488         strcat(element, sub);
489     }
490     r->protocol_version_num =
491         ill_get_enumerated(gc, element, "protocol-version-num", 
492                            ILL_Request_version_2);
493     
494     r->transaction_id = ill_get_Transaction_Id(gc, element, "transaction-id");
495     r->service_date_time =
496         ill_get_Service_Date_Time(gc, element, "service-date-time");
497     r->requester_id = ill_get_System_Id(gc, element, "requester-id");
498     r->responder_id = ill_get_System_Id(gc, element, "responder-id");
499     r->transaction_type =
500         ill_get_enumerated(gc, element, "transaction-type", 1);
501
502     r->delivery_address =
503         ill_get_Delivery_Address(gc, element, "delivery-address");
504     r->delivery_service = 0; /* TODO */
505     /* ill_get_Delivery_Service(gc, element, "delivery-service"); */
506     r->billing_address =
507         ill_get_Delivery_Address(gc, element, "billing-address");
508
509     r->num_iLL_service_type = 1;
510     r->iLL_service_type =(ILL_Service_Type **)
511         odr_malloc(o, sizeof(*r->iLL_service_type));
512     *r->iLL_service_type =
513         ill_get_enumerated(gc, element, "ill-service-type",
514                            ILL_Service_Type_copy_non_returnable);
515
516     r->responder_specific_service = 0;
517     r->requester_optional_messages =
518         ill_get_Requester_Optional_Messages_Type(
519             gc, element,"requester-optional-messages");
520     r->search_type = ill_get_Search_Type(gc, element, "search-type");
521     r->num_supply_medium_info_type = 0;
522     r->supply_medium_info_type = 0;
523
524     r->place_on_hold = ill_get_enumerated(
525         gc, element, "place-on-hold", 
526         ILL_Place_On_Hold_Type_according_to_responder_policy);
527     r->client_id = ill_get_Client_Id(gc, element, "client-id");
528                            
529     r->item_id = ill_get_Item_Id(gc, element, "item-id");
530     r->supplemental_item_description = 0;
531     r->cost_info_type = 0;
532     r->copyright_compliance =
533         ill_get_ILL_String(gc, element, "copyright-complicance");
534     r->third_party_info_type = 0;
535     r->retry_flag = ill_get_bool(gc, element, "retry-flag", 0);
536     r->forward_flag = ill_get_bool(gc, element, "forward-flag", 0);
537     r->requester_note = ill_get_ILL_String(gc, element, "requester-note");
538     r->forward_note = ill_get_ILL_String(gc, element, "forward-note");
539     r->num_iLL_request_extensions = 0;
540     r->iLL_request_extensions = 0;
541     return r;
542 }
543
544 ILL_ItemRequest *ill_get_ItemRequest(
545     struct ill_get_ctl *gc, const char *name, const char *sub)
546 {
547     ODR o = gc->odr;
548     ILL_ItemRequest *r = (ILL_ItemRequest *)odr_malloc(o, sizeof(*r));
549     char element[128];
550     
551     strcpy(element, name);
552     if (sub)
553     {
554         strcat(element, ",");
555         strcat(element, sub);
556     }
557     r->protocol_version_num =
558         ill_get_enumerated(gc, element, "protocol-version-num", 
559                            ILL_Request_version_2);
560     
561     r->transaction_id = ill_get_Transaction_Id(gc, element, "transaction-id");
562     r->service_date_time =
563         ill_get_Service_Date_Time(gc, element, "service-date-time");
564     r->requester_id = ill_get_System_Id(gc, element, "requester-id");
565     r->responder_id = ill_get_System_Id(gc, element, "responder-id");
566     r->transaction_type =
567         ill_get_enumerated(gc, element, "transaction-type", 1);
568
569     r->delivery_address =
570         ill_get_Delivery_Address(gc, element, "delivery-address");
571     r->delivery_service = 0; /* TODO */
572     /* ill_get_Delivery_Service(gc, element, "delivery-service"); */
573     r->billing_address =
574         ill_get_Delivery_Address(gc, element, "billing-address");
575
576     r->num_iLL_service_type = 1;
577     r->iLL_service_type =(ILL_Service_Type **)
578         odr_malloc(o, sizeof(*r->iLL_service_type));
579     *r->iLL_service_type =
580         ill_get_enumerated(gc, element, "ill-service-type",
581                            ILL_Service_Type_copy_non_returnable);
582
583     r->responder_specific_service = 0;
584     r->requester_optional_messages =
585         ill_get_Requester_Optional_Messages_Type(
586             gc, element,"requester-optional-messages");
587     r->search_type = ill_get_Search_Type(gc, element, "search-type");
588     r->num_supply_medium_info_type = 0;
589     r->supply_medium_info_type = 0;
590
591     r->place_on_hold = ill_get_enumerated(
592         gc, element, "place-on-hold", 
593         ILL_Place_On_Hold_Type_according_to_responder_policy);
594     r->client_id = ill_get_Client_Id(gc, element, "client-id");
595                            
596     r->item_id = ill_get_Item_Id(gc, element, "item-id");
597     r->supplemental_item_description = 0;
598     r->cost_info_type = 0;
599     r->copyright_compliance =
600         ill_get_ILL_String(gc, element, "copyright-complicance");
601     r->third_party_info_type = 0;
602     r->retry_flag = ill_get_bool(gc, element, "retry-flag", 0);
603     r->forward_flag = ill_get_bool(gc, element, "forward-flag", 0);
604     r->requester_note = ill_get_ILL_String(gc, element, "requester-note");
605     r->forward_note = ill_get_ILL_String(gc, element, "forward-note");
606     r->num_iLL_request_extensions = 0;
607     r->iLL_request_extensions = 0;
608     return r;
609 }
610
611 ILL_Cancel *ill_get_Cancel(
612     struct ill_get_ctl *gc, const char *name, const char *sub)
613 {
614     ODR o = gc->odr;
615     ILL_Cancel *r = (ILL_Cancel *)odr_malloc(o, sizeof(*r));
616     char element[128];
617     
618     strcpy(element, name);
619     if (sub)
620     {
621         strcat(element, ",");
622         strcat(element, sub);
623     }
624     r->protocol_version_num =
625         ill_get_enumerated(gc, element, "protocol-version-num", 
626                            ILL_Request_version_2);
627     
628     r->transaction_id = ill_get_Transaction_Id(gc, element, "transaction-id");
629     r->service_date_time =
630         ill_get_Service_Date_Time(gc, element, "service-date-time");
631     r->requester_id = ill_get_System_Id(gc, element, "requester-id");
632     r->responder_id = ill_get_System_Id(gc, element, "responder-id");
633     r->requester_note = ill_get_ILL_String(gc, element, "requester-note");
634
635     r->num_cancel_extensions = 0;
636     r->cancel_extensions = 0;
637     return r;
638 }
639
640 ILL_APDU *ill_get_APDU(
641     struct ill_get_ctl *gc, const char *name, const char *sub)
642 {
643     ODR o = gc->odr;
644     ILL_APDU *r = (ILL_APDU *)odr_malloc(o, sizeof(*r));
645     char element[128];
646     const char *v;
647
648     strcpy(element, name);
649     strcat(element, ",which");
650
651     v = (gc->f)(gc->clientData, element);
652     if (!v)
653         v = "request";
654     if (!strcmp(v, "request"))
655     {
656         r->which = ILL_APDU_ILL_Request;
657         r->u.illRequest = ill_get_ILLRequest(gc, name, sub);
658     }
659     else if (!strcmp(v, "cancel"))
660     {
661         r->which = ILL_APDU_Cancel;
662         r->u.Cancel = ill_get_Cancel(gc, name, sub);
663     }
664     else
665         return 0;
666     return r;
667 }
668 /*
669  * Local variables:
670  * c-basic-offset: 4
671  * c-file-style: "Stroustrup"
672  * indent-tabs-mode: nil
673  * End:
674  * vim: shiftwidth=4 tabstop=8 expandtab
675  */
676