1 /*
2                                   NETWIB
3                              Network library
4                 Copyright(c) 1999-2010 Laurent Constantin
5                                   -----
6 
7   Main server   : http://www.laurentconstantin.com/
8   Backup server : http://laurentconstantin.free.fr/
9   [my current email address is on the web servers]
10 
11                                   -----
12   This file is part of Netwib.
13 
14   Netwib is free software: you can redistribute it and/or modify
15   it under the terms of the GNU General Public License version 3
16   as published by the Free Software Foundation.
17 
18   Netwib is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details (http://www.gnu.org/).
22 
23 ------------------------------------------------------------------------
24 */
25 
26 #include <netwib/inc/maininc.h>
27 
28 /*
29                              IMPORTANT
30 Function netwib_priv_buf_append_vfmt2 must be independent, and
31 work even if netwib is not initialized : it is used in netwib_init
32 to display error. Of course, this is only valid if the buffer
33 is an external array (ie not allocated).
34 */
35 
36 /*-------------------------------------------------------------*/
netwib_priv_buf_append_vfmt_error(netwib_conststring msg)37 static netwib_err netwib_priv_buf_append_vfmt_error(netwib_conststring msg)
38 {
39   netwib_bool canuseglo;
40 
41   netwib_er(netwib_priv_glovars_canuse(&canuseglo));
42   if (canuseglo) {
43     netwib_er(netwib_priv_errmsg_string(msg));
44   }
45 
46   return(NETWIB_ERR_OK);
47 }
48 
49 /*-------------------------------------------------------------*/
netwib_priv_buf_append_vfmt_error2(netwib_conststring msg,netwib_conststring badfmt)50 static netwib_err netwib_priv_buf_append_vfmt_error2(netwib_conststring msg,
51                                                      netwib_conststring badfmt)
52 {
53   netwib_buf buf;
54   netwib_bool canuseglo;
55 
56   netwib_er(netwib_priv_glovars_canuse(&canuseglo));
57   if (canuseglo) {
58     netwib_er(netwib_buf_init_mallocdefault(&buf));
59     netwib_er(netwib_buf_append_string(msg, &buf));
60     netwib_er(netwib_buf_append_string(" in \"...%", &buf));
61     netwib_er(netwib_buf_append_string(badfmt, &buf));
62     netwib_er(netwib_buf_append_string("\"", &buf));
63     netwib_er(netwib_priv_errmsg_buf(&buf));
64     netwib_er(netwib_buf_close(&buf));
65   }
66 
67   return(NETWIB_ERR_OK);
68 }
69 
70 
71 /*-------------------------------------------------------------*/
72 /*-------------------------------------------------------------*/
73 /*-------------------------------------------------------------*/
74 /*-------------------------------------------------------------*/
75 /*-------------------------------------------------------------*/
76 
77 /*-------------------------------------------------------------*/
78 #define NETWIB_PRIV_FMT_FIELD_MAXSIZE 20
79 
80 typedef enum {
81   NETWIB_PRIV_FMT_ALIGNTYPE_LEFT = 1,
82   NETWIB_PRIV_FMT_ALIGNTYPE_CENTER,
83   NETWIB_PRIV_FMT_ALIGNTYPE_RIGHT
84 } netwib_priv_fmt_aligntype;
85 
86 typedef struct {
87   netwib_bool altformat;
88   netwib_uint32 minsize;
89   netwib_uint32 base;
90 } netwib_priv_fmt_spec_uint;
91 
92 typedef struct {
93   netwib_bool sign;
94   netwib_uint32 minsize;
95 } netwib_priv_fmt_spec_int;
96 
97 typedef struct {
98   netwib_char type;
99 } netwib_priv_fmt_spec_bool;
100 
101 typedef struct {
102   netwib_char type;
103 } netwib_priv_fmt_spec_cmp;
104 
105 typedef struct {
106   netwib_bool useglob;
107 } netwib_priv_fmt_spec_buf;
108 
109 typedef struct {
110   netwib_bool useglob;
111 } netwib_priv_fmt_spec_s;
112 
113 typedef enum {
114   NETWIB_PRIV_FMT_FIELDTYPE_PERCENT = 1,
115   NETWIB_PRIV_FMT_FIELDTYPE_C,
116   NETWIB_PRIV_FMT_FIELDTYPE_S,
117   NETWIB_PRIV_FMT_FIELDTYPE_P,
118   NETWIB_PRIV_FMT_FIELDTYPE_END,
119   NETWIB_PRIV_FMT_FIELDTYPE_UINT64,
120   NETWIB_PRIV_FMT_FIELDTYPE_UINT32,
121   NETWIB_PRIV_FMT_FIELDTYPE_UINT16,
122   NETWIB_PRIV_FMT_FIELDTYPE_UINT8,
123   NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX,
124   NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR,
125   NETWIB_PRIV_FMT_FIELDTYPE_BYTE,
126   NETWIB_PRIV_FMT_FIELDTYPE_INT64,
127   NETWIB_PRIV_FMT_FIELDTYPE_INT32,
128   NETWIB_PRIV_FMT_FIELDTYPE_INT16,
129   NETWIB_PRIV_FMT_FIELDTYPE_INT8,
130   NETWIB_PRIV_FMT_FIELDTYPE_INTMAX,
131   NETWIB_PRIV_FMT_FIELDTYPE_INTPTR,
132   NETWIB_PRIV_FMT_FIELDTYPE_BOOL,
133   NETWIB_PRIV_FMT_FIELDTYPE_CMP,
134   NETWIB_PRIV_FMT_FIELDTYPE_BUF,
135   NETWIB_PRIV_FMT_FIELDTYPE_ETH,
136   NETWIB_PRIV_FMT_FIELDTYPE_IP,
137   NETWIB_PRIV_FMT_FIELDTYPE_PORT,
138   NETWIB_PRIV_FMT_FIELDTYPE_ETHS,
139   NETWIB_PRIV_FMT_FIELDTYPE_IPS,
140   NETWIB_PRIV_FMT_FIELDTYPE_PORTS
141 } netwib_priv_fmt_fieldtype;
142 
143 typedef struct {
144   netwib_uint32 skipsize;
145   netwib_priv_fmt_fieldtype fieldtype;
146   /* below are not always set */
147   netwib_bool geneset;
148   struct {
149     netwib_priv_fmt_aligntype align;
150     netwib_char padchar;
151     netwib_uint32 minsize;
152     netwib_bool skipfield;
153   } gene;
154   netwib_bool specset;
155   union {
156     netwib_priv_fmt_spec_uint specuint;
157     netwib_priv_fmt_spec_int specint;
158     netwib_priv_fmt_spec_bool specbool;
159     netwib_priv_fmt_spec_cmp speccmp;
160     netwib_priv_fmt_spec_buf specbuf;
161     netwib_priv_fmt_spec_s specs;
162   } spec;
163 } netwib_priv_fmtinfos;
164 
165 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_type(netwib_conststring fmt,netwib_conststring type,netwib_priv_fmtinfos * pinfos)166 static netwib_err netwib_priv_fmt_analyze_type(netwib_conststring fmt,
167                                                netwib_conststring type,
168                                                netwib_priv_fmtinfos *pinfos)
169 {
170 
171   netwib_uint32 datasize;
172   netwib_char firstchar;
173 
174   datasize = netwib_c_strlen(type);
175   if (datasize == 0) {
176     return(NETWIB_ERR_PAFMT);
177   }
178 
179 #define netwib__priv_fmt_analyze_type_cmp(txt,val) if (!netwib_c_memcmp(type, txt, datasize)) { pinfos->fieldtype = val; return(NETWIB_ERR_OK); }
180   firstchar = type[0];
181   switch(firstchar) {
182   case 'b' :
183     switch (datasize) {
184     case 3 :
185       netwib__priv_fmt_analyze_type_cmp("buf",
186                                         NETWIB_PRIV_FMT_FIELDTYPE_BUF);
187       break;
188     case 4 :
189       netwib__priv_fmt_analyze_type_cmp("bool",
190                                         NETWIB_PRIV_FMT_FIELDTYPE_BOOL);
191       netwib__priv_fmt_analyze_type_cmp("byte",
192                                         NETWIB_PRIV_FMT_FIELDTYPE_BYTE);
193       break;
194     }
195     break;
196   case 'c' :
197     switch (datasize) {
198     case 1 :
199       pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_C;
200       return(NETWIB_ERR_OK);
201       break;
202     case 3 :
203       netwib__priv_fmt_analyze_type_cmp("cmp",
204                                         NETWIB_PRIV_FMT_FIELDTYPE_CMP);
205       break;
206     }
207     break;
208   case 'e' :
209     switch (datasize) {
210     case 3 :
211       netwib__priv_fmt_analyze_type_cmp("eth",
212                                         NETWIB_PRIV_FMT_FIELDTYPE_ETH);
213       break;
214     case 4 :
215       netwib__priv_fmt_analyze_type_cmp("eths",
216                                         NETWIB_PRIV_FMT_FIELDTYPE_ETHS);
217       break;
218     }
219     break;
220   case 'i' :
221     switch (datasize) {
222     case 2 :
223       netwib__priv_fmt_analyze_type_cmp("ip",
224                                         NETWIB_PRIV_FMT_FIELDTYPE_IP);
225       break;
226     case 3 :
227       netwib__priv_fmt_analyze_type_cmp("ips",
228                                         NETWIB_PRIV_FMT_FIELDTYPE_IPS);
229       break;
230     case 4 :
231       netwib__priv_fmt_analyze_type_cmp("int8",
232                                         NETWIB_PRIV_FMT_FIELDTYPE_INT8);
233       break;
234     case 5 :
235       netwib__priv_fmt_analyze_type_cmp("int32",
236                                         NETWIB_PRIV_FMT_FIELDTYPE_INT32);
237       netwib__priv_fmt_analyze_type_cmp("int16",
238                                         NETWIB_PRIV_FMT_FIELDTYPE_INT16);
239       netwib__priv_fmt_analyze_type_cmp("int64",
240                                         NETWIB_PRIV_FMT_FIELDTYPE_INT64);
241       break;
242     case 6 :
243       netwib__priv_fmt_analyze_type_cmp("intmax",
244                                         NETWIB_PRIV_FMT_FIELDTYPE_INTMAX);
245       netwib__priv_fmt_analyze_type_cmp("intptr",
246                                         NETWIB_PRIV_FMT_FIELDTYPE_INTPTR);
247       break;
248     }
249     break;
250   case 'p' :
251     switch (datasize) {
252     case 1 :
253       pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_P;
254       return(NETWIB_ERR_OK);
255       break;
256     case 4 :
257       netwib__priv_fmt_analyze_type_cmp("port",
258                                         NETWIB_PRIV_FMT_FIELDTYPE_PORT);
259       break;
260     case 5 :
261       netwib__priv_fmt_analyze_type_cmp("ports",
262                                         NETWIB_PRIV_FMT_FIELDTYPE_PORTS);
263       break;
264     }
265     break;
266   case 's' :
267     switch (datasize) {
268     case 1 :
269       pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_S;
270       return(NETWIB_ERR_OK);
271       break;
272     }
273     break;
274   case 'u' :
275     switch (datasize) {
276     case 5 :
277       netwib__priv_fmt_analyze_type_cmp("uint8",
278                                         NETWIB_PRIV_FMT_FIELDTYPE_UINT8);
279       break;
280     case 6 :
281       netwib__priv_fmt_analyze_type_cmp("uint32",
282                                         NETWIB_PRIV_FMT_FIELDTYPE_UINT32);
283       netwib__priv_fmt_analyze_type_cmp("uint16",
284                                         NETWIB_PRIV_FMT_FIELDTYPE_UINT16);
285       netwib__priv_fmt_analyze_type_cmp("uint64",
286                                         NETWIB_PRIV_FMT_FIELDTYPE_UINT64);
287       break;
288     case 7 :
289       netwib__priv_fmt_analyze_type_cmp("uintmax",
290                                         NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX);
291       netwib__priv_fmt_analyze_type_cmp("uintptr",
292                                         NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR);
293       break;
294     }
295     break;
296   }
297 
298   netwib_er(netwib_priv_buf_append_vfmt_error2("type not recognized", fmt));
299   return(NETWIB_ERR_PAFMT);
300 }
301 
302 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_gene(netwib_conststring fmt,netwib_conststring gene,netwib_priv_fmtinfos * pinfos)303 static netwib_err netwib_priv_fmt_analyze_gene(netwib_conststring fmt,
304                                                netwib_conststring gene,
305                                                netwib_priv_fmtinfos *pinfos)
306 {
307   netwib_conststring pgene;
308 
309   /* set default values */
310   pinfos->geneset = NETWIB_TRUE;
311   pinfos->gene.align = NETWIB_PRIV_FMT_ALIGNTYPE_LEFT;
312   pinfos->gene.padchar = ' ';
313   pinfos->gene.minsize = 0;
314   pinfos->gene.skipfield = NETWIB_FALSE;
315 
316   /* decode pgene expressed as a regexp : "[*]{0,1}[lcr].[1-9][0-9]{0,1}"
317      or simply "[*]{0,1}" */
318   pgene = gene;
319 
320   if (*pgene == '*') {
321     pinfos->gene.skipfield = NETWIB_TRUE;
322     pgene++;
323     if (*pgene == '\0') {
324       /* stop here */
325       return(NETWIB_ERR_OK);
326     }
327   }
328 
329   switch(*pgene) {
330     case 'l' :
331       pinfos->gene.align = NETWIB_PRIV_FMT_ALIGNTYPE_LEFT;
332       break;
333     case 'c' :
334       pinfos->gene.align = NETWIB_PRIV_FMT_ALIGNTYPE_CENTER;
335       break;
336     case 'r' :
337       pinfos->gene.align = NETWIB_PRIV_FMT_ALIGNTYPE_RIGHT;
338       break;
339     default :
340       netwib_er(netwib_priv_buf_append_vfmt_error2("generic should start with l, c or r",
341                                                  fmt));
342       return(NETWIB_ERR_PAFMT);
343   }
344   pgene++;
345 
346   /* obtain padding */
347   if (*pgene == '\0') {
348     netwib_er(netwib_priv_buf_append_vfmt_error2("the padding char is missing",
349                                                fmt));
350     return(NETWIB_ERR_PAFMT);
351   }
352   pinfos->gene.padchar = *pgene++;
353 
354   /* obtain minsize */
355   if (!netwib_c2_isdigit(*pgene)) {
356     netwib_er(netwib_priv_buf_append_vfmt_error2("the size is missing", fmt));
357     return(NETWIB_ERR_PAFMT);
358   }
359   pinfos->gene.minsize = netwib_c2_cto9(*pgene);
360   pgene++;
361   if (netwib_c2_isdigit(*pgene)) {
362     pinfos->gene.minsize *= 10;
363     pinfos->gene.minsize += netwib_c2_cto9(*pgene);
364     pgene++;
365   }
366 
367   if (*pgene != '\0') {
368     netwib_er(netwib_priv_buf_append_vfmt_error2("specific parameter is too long",
369                                                fmt));
370     return(NETWIB_ERR_PAFMT);
371   }
372 
373   return(NETWIB_ERR_OK);
374 }
375 
376 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_spec_s(netwib_conststring fmt,netwib_conststring spec,netwib_priv_fmt_spec_s * ps)377 static netwib_err netwib_priv_fmt_analyze_spec_s(netwib_conststring fmt,
378                                                  netwib_conststring spec,
379                                                  netwib_priv_fmt_spec_s *ps)
380 {
381 
382   /* set default values */
383   ps->useglob = NETWIB_FALSE;
384 
385   if (spec == NULL) {
386     return(NETWIB_ERR_OK);
387   }
388 
389   if (!netwib_c_strcmp(spec, "glob")) {
390     ps->useglob = NETWIB_TRUE;
391   } else {
392     netwib_er(netwib_priv_buf_append_vfmt_error2("specific is not recognized",
393                                                fmt));
394     return(NETWIB_ERR_PAFMT);
395   }
396 
397   return(NETWIB_ERR_OK);
398 }
399 
400 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_spec_uint(netwib_conststring fmt,netwib_conststring spec,netwib_priv_fmt_spec_uint * ps)401 static netwib_err netwib_priv_fmt_analyze_spec_uint(netwib_conststring fmt,
402                                                     netwib_conststring spec,
403                                                     netwib_priv_fmt_spec_uint *ps)
404 {
405   netwib_conststring pspec;
406 
407   /* set default values */
408   ps->altformat = NETWIB_FALSE;
409   ps->minsize = 0;
410   ps->base = 10;
411 
412   if (spec == NULL) {
413     return(NETWIB_ERR_OK);
414   }
415   pspec = spec;
416 
417   /* analyze pspec which should contain "[0]{0,1}[0-9]{0,2}[bouxX]" */
418 
419   /* set alternative format */
420   if (*pspec == '#') {
421     ps->altformat = NETWIB_TRUE;
422     pspec++;
423   }
424 
425   /* set minsize */
426   if (netwib_c2_isdigit(*pspec)) {
427       ps->minsize = netwib_c2_cto9(*pspec);
428       pspec++;
429   }
430   if (netwib_c2_isdigit(*pspec)) {
431     ps->minsize *= 10;
432     ps->minsize += netwib_c2_cto9(*pspec);
433     pspec++;
434   }
435 
436   /* set base */
437   switch (*pspec) {
438     case 'b' :
439       ps->base = 2;
440       pspec++;
441       break;
442     case 'o' :
443       ps->base = 8;
444       pspec++;
445       break;
446     case 'u' :
447       ps->base = 10;
448       pspec++;
449       break;
450     case 'x' :
451       ps->base = 16;
452       pspec++;
453       break;
454     case 'X' :
455       ps->base = 17;
456       pspec++;
457       break;
458     case '\0' :
459       break;
460     default :
461       netwib_er(netwib_priv_buf_append_vfmt_error2("specific base is not b, o, u, x or X", fmt));
462       return(NETWIB_ERR_PAFMT);
463   }
464 
465   /* now, should be empty */
466   if (*pspec != '\0') {
467     netwib_er(netwib_priv_buf_append_vfmt_error2("specific base is not recognized", fmt));
468     return(NETWIB_ERR_PAFMT);
469   }
470 
471   return(NETWIB_ERR_OK);
472 }
473 
474 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_spec_int(netwib_conststring fmt,netwib_conststring spec,netwib_priv_fmt_spec_int * ps)475 static netwib_err netwib_priv_fmt_analyze_spec_int(netwib_conststring fmt,
476                                                    netwib_conststring spec,
477                                                    netwib_priv_fmt_spec_int *ps)
478 {
479   netwib_conststring pspec;
480 
481   /* set default values */
482   ps->sign = NETWIB_FALSE;
483   ps->minsize = 0;
484 
485   if (spec == NULL) {
486     return(NETWIB_ERR_OK);
487   }
488   pspec = spec;
489 
490   /* analyze pspec which should contain "[+]{0,1}[0-9]{0,2}" */
491 
492   /* set sign */
493   if (*pspec == '+') {
494     ps->sign = NETWIB_TRUE;
495     pspec++;
496   }
497 
498   /* set minsize */
499   if (netwib_c2_isdigit(*pspec)) {
500     ps->minsize = netwib_c2_cto9(*pspec);
501     pspec++;
502   }
503   if (netwib_c2_isdigit(*pspec)) {
504     ps->minsize *= 10;
505     ps->minsize += netwib_c2_cto9(*pspec);
506     pspec++;
507   }
508 
509   /* now, should be empty */
510   if (*pspec != '\0') {
511     netwib_er(netwib_priv_buf_append_vfmt_error2("specific base is not recognized", fmt));
512     return(NETWIB_ERR_PAFMT);
513   }
514 
515   return(NETWIB_ERR_OK);
516 }
517 
518 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_spec_bool(netwib_conststring fmt,netwib_conststring spec,netwib_priv_fmt_spec_bool * ps)519 static netwib_err netwib_priv_fmt_analyze_spec_bool(netwib_conststring fmt,
520                                                     netwib_conststring spec,
521                                                     netwib_priv_fmt_spec_bool *ps)
522 {
523   netwib_conststring pspec;
524 
525   /* set default value */
526   ps->type = 't';
527 
528   if (spec == NULL) {
529     return(NETWIB_ERR_OK);
530   }
531   pspec = spec;
532 
533   /* analyze pspec which should contain "[0tTyYsS]{0,1}" */
534   switch(*pspec) {
535     case '0' :
536     case 't' :
537     case 'T' :
538     case 'y' :
539     case 'Y' :
540     case 's' :
541     case 'S' :
542       ps->type = *pspec;
543       break;
544     default :
545       netwib_er(netwib_priv_buf_append_vfmt_error2("specific is not 0, t, T, y, Y, s or S", fmt));
546       return(NETWIB_ERR_PAFMT);
547       break;
548   }
549 
550   return(NETWIB_ERR_OK);
551 }
552 
553 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_spec_cmp(netwib_conststring fmt,netwib_conststring spec,netwib_priv_fmt_spec_cmp * ps)554 static netwib_err netwib_priv_fmt_analyze_spec_cmp(netwib_conststring fmt,
555                                                    netwib_conststring spec,
556                                                    netwib_priv_fmt_spec_cmp *ps)
557 {
558   netwib_conststring pspec;
559 
560   /* set default value */
561   ps->type = 't';
562 
563   if (spec == NULL) {
564     return(NETWIB_ERR_OK);
565   }
566   pspec = spec;
567 
568   /* analyze pspec which should contain "[=0e]{0,1}" */
569   switch(*pspec) {
570     case '=' :
571     case '0' :
572     case 'e' :
573       ps->type = *pspec;
574       break;
575     default :
576       netwib_er(netwib_priv_buf_append_vfmt_error2("specific is not =, 0 or e",
577                                                  fmt));
578       return(NETWIB_ERR_PAFMT);
579       break;
580   }
581 
582   return(NETWIB_ERR_OK);
583 }
584 
585 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze_spec_buf(netwib_conststring fmt,netwib_conststring spec,netwib_priv_fmt_spec_buf * ps)586 static netwib_err netwib_priv_fmt_analyze_spec_buf(netwib_conststring fmt,
587                                                    netwib_conststring spec,
588                                                    netwib_priv_fmt_spec_buf *ps)
589 {
590 
591   /* set default values */
592   ps->useglob = NETWIB_FALSE;
593 
594   if (spec == NULL) {
595     return(NETWIB_ERR_OK);
596   }
597 
598   if (!netwib_c_strcmp(spec, "glob")) {
599     ps->useglob = NETWIB_TRUE;
600   } else {
601     netwib_er(netwib_priv_buf_append_vfmt_error2("specific is not recognized",
602                                                fmt));
603     return(NETWIB_ERR_PAFMT);
604   }
605 
606   return(NETWIB_ERR_OK);
607 }
608 
609 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze2(netwib_conststring fmt,netwib_priv_fmtinfos * pinfos)610 static netwib_err netwib_priv_fmt_analyze2(netwib_conststring fmt,
611                                            netwib_priv_fmtinfos *pinfos)
612 {
613   netwib_char array[3][NETWIB_PRIV_FMT_FIELD_MAXSIZE+1];
614   netwib_conststring pfmt;
615   netwib_string pgene, ptype, pspec;
616   netwib_char c;
617   netwib_uint32 setsize, storeinarray;
618   netwib_bool continuetoloop;
619 
620   /*
621     Decompose generalformat;type:specificformat :
622       %{type}
623       %{generalformat;type:specificformat}
624       %{generalformat;type}
625       %{type:specificformat}
626   */
627 
628   pfmt = fmt + 1;
629   setsize = 0;
630   storeinarray = 0;
631   pgene = NULL;
632   ptype = NULL;
633   pspec = NULL;
634   continuetoloop = NETWIB_TRUE;
635   while (continuetoloop) {
636     c = *pfmt++;
637     switch (c) {
638       case '\0' :
639         netwib_er(netwib_priv_buf_append_vfmt_error2("character '}' not found",
640                                                      fmt));
641         return(NETWIB_ERR_PAFMT);
642       case '}' :
643         array[storeinarray][setsize] = '\0';
644         if (storeinarray == 0) {
645           ptype = (netwib_string)&(array[storeinarray]);
646         } else if (storeinarray == 1) {
647           if (ptype == NULL) {
648             ptype = (netwib_string)&(array[storeinarray]);
649           } else {
650             pspec = (netwib_string)&(array[storeinarray]);
651           }
652         } else {
653           pspec = (netwib_string)&(array[storeinarray]);
654         }
655         continuetoloop = NETWIB_FALSE;
656         break;
657       case ';' :
658         array[storeinarray][setsize] = '\0';
659         if (storeinarray == 0) {
660           pgene = (netwib_string)&(array[storeinarray]);
661           storeinarray++;
662           setsize = 0;
663         } else {
664           netwib_er(netwib_priv_buf_append_vfmt_error2("char ';' found too late", fmt));
665           return(NETWIB_ERR_PAFMT);
666         }
667         break;
668       case ':' :
669         array[storeinarray][setsize] = '\0';
670         if (storeinarray == 2) {
671           netwib_er(netwib_priv_buf_append_vfmt_error2("char ':' found too late", fmt));
672           return(NETWIB_ERR_PAFMT);
673         } else {
674           ptype = (netwib_string)&(array[storeinarray]);
675           storeinarray++;
676           setsize = 0;
677         }
678         break;
679       default :
680         array[storeinarray][setsize++] = c;
681     }
682     if (setsize > NETWIB_PRIV_FMT_FIELD_MAXSIZE) {
683       netwib_er(netwib_priv_buf_append_vfmt_error2("format is too long", fmt));
684       return(NETWIB_ERR_PAFMT);
685     }
686   }
687 
688   /* reset pointers if string are empty */
689   if (pgene != NULL && pgene[0] == '\0') pgene = NULL;
690   if (ptype != NULL && ptype[0] == '\0') ptype = NULL;
691   if (pspec != NULL && pspec[0] == '\0') pspec = NULL;
692 
693   /* set info values */
694   pinfos->skipsize = pfmt - fmt;
695 
696   if (ptype == NULL) {
697     netwib_er(netwib_priv_buf_append_vfmt_error2("format type must be present",
698                                                  fmt));
699     return(NETWIB_ERR_PAFMT);
700   }
701   netwib_er(netwib_priv_fmt_analyze_type(fmt, ptype, pinfos));
702 
703   if (pgene == NULL) {
704     pinfos->geneset = NETWIB_FALSE;
705   } else {
706     netwib_er(netwib_priv_fmt_analyze_gene(fmt, pgene, pinfos));
707   }
708 
709   switch(pinfos->fieldtype) {
710     case NETWIB_PRIV_FMT_FIELDTYPE_UINT32 :
711     case NETWIB_PRIV_FMT_FIELDTYPE_UINT16 :
712     case NETWIB_PRIV_FMT_FIELDTYPE_UINT8 :
713     case NETWIB_PRIV_FMT_FIELDTYPE_UINT64 :
714     case NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX :
715     case NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR :
716     case NETWIB_PRIV_FMT_FIELDTYPE_BYTE :
717       netwib_er(netwib_priv_fmt_analyze_spec_uint(fmt, pspec,
718                                                   &pinfos->spec.specuint));
719       pinfos->specset = NETWIB_TRUE;
720       break;
721     case NETWIB_PRIV_FMT_FIELDTYPE_INT32 :
722     case NETWIB_PRIV_FMT_FIELDTYPE_INT16 :
723     case NETWIB_PRIV_FMT_FIELDTYPE_INT8 :
724     case NETWIB_PRIV_FMT_FIELDTYPE_INT64 :
725     case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
726     case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
727       netwib_er(netwib_priv_fmt_analyze_spec_int(fmt, pspec,
728                                                  &pinfos->spec.specint));
729       pinfos->specset = NETWIB_TRUE;
730       break;
731     case NETWIB_PRIV_FMT_FIELDTYPE_BOOL :
732       if (pspec == NULL) {
733         pinfos->specset = NETWIB_FALSE;
734       } else {
735         netwib_er(netwib_priv_fmt_analyze_spec_bool(fmt, pspec,
736                                                     &pinfos->spec.specbool));
737         pinfos->specset = NETWIB_TRUE;
738       }
739       break;
740     case NETWIB_PRIV_FMT_FIELDTYPE_CMP :
741       if (pspec == NULL) {
742         pinfos->specset = NETWIB_FALSE;
743       } else {
744         netwib_er(netwib_priv_fmt_analyze_spec_cmp(fmt, pspec,
745                                                  &pinfos->spec.speccmp));
746         pinfos->specset = NETWIB_TRUE;
747       }
748       break;
749     case NETWIB_PRIV_FMT_FIELDTYPE_S :
750       netwib_er(netwib_priv_fmt_analyze_spec_s(fmt, pspec,
751                                                &pinfos->spec.specs));
752       pinfos->specset = NETWIB_TRUE;
753       break;
754     case NETWIB_PRIV_FMT_FIELDTYPE_BUF :
755       netwib_er(netwib_priv_fmt_analyze_spec_buf(fmt, pspec,
756                                                &pinfos->spec.specbuf));
757       pinfos->specset = NETWIB_TRUE;
758       break;
759     case NETWIB_PRIV_FMT_FIELDTYPE_C :
760     case NETWIB_PRIV_FMT_FIELDTYPE_P :
761     case NETWIB_PRIV_FMT_FIELDTYPE_ETH :
762     case NETWIB_PRIV_FMT_FIELDTYPE_IP :
763     case NETWIB_PRIV_FMT_FIELDTYPE_PORT :
764     case NETWIB_PRIV_FMT_FIELDTYPE_ETHS :
765     case NETWIB_PRIV_FMT_FIELDTYPE_IPS :
766     case NETWIB_PRIV_FMT_FIELDTYPE_PORTS :
767       if (pspec == NULL) {
768         pinfos->specset = NETWIB_FALSE;
769       } else {
770         netwib_er(netwib_priv_buf_append_vfmt_error2("there should be no specific parameter", fmt));
771         return(NETWIB_ERR_PAFMT);
772       }
773       break;
774     case NETWIB_PRIV_FMT_FIELDTYPE_PERCENT :
775     case NETWIB_PRIV_FMT_FIELDTYPE_END :
776       return(NETWIB_ERR_LOINTERNALERROR);
777       break;
778   }
779 
780   return(NETWIB_ERR_OK);
781 }
782 
783 /*-------------------------------------------------------------*/
netwib_priv_fmt_analyze(netwib_conststring fmt,netwib_priv_fmtinfos * pinfos)784 static netwib_err netwib_priv_fmt_analyze(netwib_conststring fmt,
785                                           netwib_priv_fmtinfos *pinfos)
786 {
787   char fmtfirstchar;
788 
789   fmtfirstchar = *fmt;
790 
791   pinfos->geneset = NETWIB_FALSE;
792   pinfos->specset = NETWIB_FALSE;
793 
794   /* fmt ends */
795   if (fmtfirstchar == '\0') {
796     netwib_er(netwib_priv_buf_append_vfmt_error("format ends with '%'"));
797     return(NETWIB_ERR_PAFMT);
798   }
799 
800   /* character '%' */
801   if (fmtfirstchar == '%') {
802     pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_PERCENT;
803     pinfos->skipsize = 1;
804     return(NETWIB_ERR_OK);
805   }
806 
807   /* char */
808   if (fmtfirstchar == 'c') {
809     pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_C;
810     pinfos->skipsize = 1;
811     return(NETWIB_ERR_OK);
812   }
813 
814   /* string */
815   if (fmtfirstchar == 's') {
816     pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_S;
817     pinfos->skipsize = 1;
818     return(NETWIB_ERR_OK);
819   }
820 
821   /* pointer */
822   if (fmtfirstchar == 'p') {
823     pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_P;
824     pinfos->skipsize = 1;
825     return(NETWIB_ERR_OK);
826   }
827 
828   /* end */
829   if (fmtfirstchar == '$') {
830     pinfos->fieldtype = NETWIB_PRIV_FMT_FIELDTYPE_END;
831     pinfos->skipsize = 1;
832     return(NETWIB_ERR_OK);
833   }
834 
835   /* specific type */
836   if (fmtfirstchar == '{') {
837     netwib_er(netwib_priv_fmt_analyze2(fmt, pinfos));
838     return(NETWIB_ERR_OK);
839   }
840 
841   netwib_er(netwib_priv_buf_append_vfmt_error2("format is not recognized",
842                                                fmt));
843   return(NETWIB_ERR_PAFMT);
844 }
845 
846 
847 /*-------------------------------------------------------------*/
848 /*-------------------------------------------------------------*/
849 /*-------------------------------------------------------------*/
850 /*-------------------------------------------------------------*/
851 
852 /*-------------------------------------------------------------*/
853 /* 99 + '\0' = 100 characters. Do not define NETWIB_PRIV_FMT_ARR_SIZE
854    to less than 100 (not checked). */
855 #define NETWIB_PRIV_FMT_ARR_SIZE 100
856 
857 /*-------------------------------------------------------------*/
858 static netwib_uint64 netwib_priv_fmt_ui64_unused;
859 #define netwib_priv_fmt_append_uintmax(uimax,ps,array) netwib_priv_fmt_append_uint(NETWIB_TRUE,uimax,netwib_priv_fmt_ui64_unused,ps,array)
860 #if NETWIB_INT64_FAKE == 0
861  #define netwib_priv_fmt_append_uint64(ui64,ps,array) netwib_priv_fmt_append_uint(NETWIB_TRUE,ui64,netwib_priv_fmt_ui64_unused,ps,array)
862 #else
863  #define netwib_priv_fmt_append_uint64(ui64,ps,array) netwib_priv_fmt_append_uint(NETWIB_FALSE,0,ui64,ps,array)
864 #endif
netwib_priv_fmt_append_uint(netwib_bool usemax,netwib_uintmax uimax,netwib_uint64 ui64,netwib_priv_fmt_spec_uint * ps,netwib_string array)865 static netwib_err netwib_priv_fmt_append_uint(netwib_bool usemax,
866                                               netwib_uintmax uimax,
867                                               netwib_uint64 ui64,
868                                               netwib_priv_fmt_spec_uint *ps,
869                                               netwib_string array)
870 {
871   netwib_char localarray[NETWIB_PRIV_FMT_ARR_SIZE], *ploc, c;
872   netwib_string pout;
873   netwib_uint32 nbdigit, nbzeroes, c32, base32;
874   netwib_uint64 zero;
875 
876   netwib__uint64_init_uint32(0, zero);
877 
878   nbdigit = 0;
879   base32 = ps->base;
880   if (ps->base == 17) base32 = 16;
881   if (usemax && uimax != 0) {
882     netwib_uintmax uidivbase, uidivbaseperbase;
883     do {
884       uidivbase = uimax / base32;
885       uidivbaseperbase = uidivbase * base32;
886       c32 = (netwib_uint32)(uimax - uidivbaseperbase);
887       if (ps->base == 17) {
888         c = netwib_c2_16toC(c32);
889       } else {
890         c = netwib_c2_16toc(c32);
891       }
892       localarray[nbdigit++] = c;
893       uimax = uidivbase;
894     } while (uimax != 0);
895   } else if (!usemax && netwib__uint64_cmp_ne(ui64, zero)) {
896     netwib_uint64 base64, uidivbase, uidivbaseperbase, c64, remainder;
897     netwib__uint64_init_uint32(base32, base64);
898     do {
899       netwib__uint64_div(ui64, base64, &uidivbase, &remainder);
900       netwib__uint64_mul(uidivbase, base64, &uidivbaseperbase);
901       netwib__uint64_sub(ui64, uidivbaseperbase, c64);
902       netwib__uint32_init_uint64(c64, c32);
903       if (ps->base == 17) {
904         c = netwib_c2_16toC(c32);
905       } else {
906         c = netwib_c2_16toc(c32);
907       }
908       localarray[nbdigit++] = c;
909       ui64 = uidivbase;
910     } while (netwib__uint64_cmp_ne(ui64, zero));
911   } else {
912     localarray[nbdigit++] = '0';
913   }
914   localarray[nbdigit] = '\0';
915 
916   if (ps->minsize == 0) {
917     nbzeroes = 0;
918   } else {
919     if (nbdigit >= ps->minsize) {
920       nbzeroes = 0;
921     } else {
922       nbzeroes = ps->minsize - nbdigit;
923     }
924   }
925 
926   ploc = localarray + nbdigit;
927   pout = array;
928   switch(ps->base) {
929   case 2 :
930     if (ps->altformat) {
931       *pout++ = 'b';
932     }
933     while (nbzeroes) {
934       *pout++ = '0';
935       nbzeroes--;
936     }
937     break;
938   case 8 :
939     if (ps->altformat) {
940       *pout++ = '0';
941     }
942     while (nbzeroes) {
943       *pout++ = '0';
944       nbzeroes--;
945     }
946     break;
947   case 10 :
948     while (nbzeroes) {
949       *pout++ = ' ';
950       nbzeroes--;
951     }
952     break;
953   case 16 :
954   case 17 :
955     if (ps->altformat) {
956       *pout++ = '0';
957       *pout++ = 'x';
958     }
959     while (nbzeroes) {
960       *pout++ = '0';
961       nbzeroes--;
962     }
963     break;
964   default :
965     return(NETWIB_ERR_LOINTERNALERROR);
966   }
967   while (nbdigit) {
968     *pout++ = *--ploc;
969     nbdigit--;
970   }
971   *pout++ = '\0';
972 
973   return(NETWIB_ERR_OK);
974 }
975 
976 /*-------------------------------------------------------------*/
977 #define netwib_priv_fmt_append_intmax(imax,ps,array) netwib_priv_fmt_append_int(NETWIB_TRUE,imax,netwib_priv_fmt_ui64_unused,ps,array)
978 #if NETWIB_INT64_FAKE == 0
979  #define netwib_priv_fmt_append_int64(i64,ps,array) netwib_priv_fmt_append_int(NETWIB_TRUE,i64,netwib_priv_fmt_ui64_unused,ps,array)
980 #else
981  #define netwib_priv_fmt_append_int64(i64,ps,array) netwib_priv_fmt_append_int(NETWIB_FALSE,0,i64,ps,array)
982 #endif
netwib_priv_fmt_append_int(netwib_bool usemax,netwib_intmax imax,netwib_int64 i64,netwib_priv_fmt_spec_int * ps,netwib_string array)983 static netwib_err netwib_priv_fmt_append_int(netwib_bool usemax,
984                                              netwib_intmax imax,
985                                              netwib_int64 i64,
986                                              netwib_priv_fmt_spec_int *ps,
987                                              netwib_string array)
988 {
989   netwib_priv_fmt_spec_uint su;
990   netwib_uint32 startat;
991   netwib_uintmax uimax=0;
992   netwib_uint64 ui64, zero;
993   netwib_cmp cmp;
994 
995   netwib__uint64_init_uint32(0, ui64);
996 
997   cmp = NETWIB_CMP_LT;
998   if (usemax) {
999     if (imax == 0) {
1000       cmp = NETWIB_CMP_EQ;
1001     } else if (imax > 0) {
1002       cmp = NETWIB_CMP_GT;
1003     }
1004   } else {
1005     netwib__uint64_init_uint32(0, zero);
1006     if (netwib__int64_cmp_eq(i64, zero)) {
1007       cmp = NETWIB_CMP_EQ;
1008     } else if (netwib__int64_cmp_gt(i64, zero)) {
1009       cmp = NETWIB_CMP_GT;
1010     }
1011   }
1012 
1013   /* eventually put a sign */
1014   startat = 0;
1015   if (cmp == NETWIB_CMP_LT) {
1016     if (usemax) {
1017       uimax = (netwib_uintmax)-imax;
1018     } else {
1019       netwib__int64_neg(i64, ui64);
1020     }
1021     /* put a '-' */
1022     array[0] = '-';
1023     startat = 1;
1024   } else {
1025     if (usemax) {
1026       uimax = (netwib_uintmax)imax;
1027     } else {
1028       ui64 = (netwib_uint64)i64;
1029     }
1030     /* eventually put a '+' (nothing for zero) */
1031     if (ps->sign && cmp == NETWIB_CMP_GT) {
1032       array[0] = '+';
1033       startat = 1;
1034     }
1035   }
1036   if (startat) {
1037     /* shrink minsize */
1038     if (ps->minsize) {
1039       ps->minsize--;
1040     }
1041   }
1042 
1043   su.altformat = NETWIB_FALSE;
1044   su.minsize = ps->minsize;
1045   su.base = 10;
1046   netwib_er(netwib_priv_fmt_append_uint(usemax, uimax, ui64,
1047                                         &su, array+startat));
1048 
1049   return(NETWIB_ERR_OK);
1050 }
1051 
1052 /*-------------------------------------------------------------*/
netwib_priv_fmt_append_eth(netwib_consteth * peth,netwib_string array)1053 static netwib_err netwib_priv_fmt_append_eth(netwib_consteth *peth,
1054                                              netwib_string array)
1055 {
1056   netwib_string parray;
1057   netwib_uint32 ethbyte, ethquartet;
1058   netwib_uint32 i;
1059 
1060   parray = array;
1061   for (i = 0; i < 6; i++) {
1062     ethbyte = peth->b[i];
1063     ethquartet = (ethbyte>>4) & 0x0F;
1064     *parray++ = netwib_c2_16toC(ethquartet);
1065     ethquartet = ethbyte & 0x0F;
1066     *parray++ = netwib_c2_16toC(ethquartet);
1067     if (i != 5) {
1068       *parray++ = ':';
1069     }
1070   }
1071   *parray ='\0';
1072 
1073   return(NETWIB_ERR_OK);
1074 }
1075 
1076 /*-------------------------------------------------------------*/
netwib_priv_fmt_append_gene(netwib_conststring str,netwib_priv_fmtinfos * pinfos,netwib_buf * pbuf)1077 static netwib_err netwib_priv_fmt_append_gene(netwib_conststring str,
1078                                               netwib_priv_fmtinfos *pinfos,
1079                                               netwib_buf *pbuf)
1080 {
1081   netwib_char localarray[NETWIB_PRIV_FMT_ARR_SIZE], *ploc;
1082   netwib_conststring pstr;
1083   netwib_uint32 strlenstr, nbpad, nbpadl, nbpadr;
1084   netwib_err ret;
1085 
1086   if (pinfos->gene.minsize > NETWIB_PRIV_FMT_ARR_SIZE-1) {
1087     return(NETWIB_ERR_LOINTERNALERROR);
1088   }
1089 
1090   /* simple case */
1091   strlenstr = netwib_c_strlen(str);
1092   if (pinfos->gene.minsize <= strlenstr) {
1093     netwib_er(netwib_buf_append_string(str, pbuf));
1094     return(NETWIB_ERR_OK);
1095   }
1096 
1097   /* compute padding */
1098   nbpadl = 0; /* for compiler warning */
1099   nbpadr = 0; /* for compiler warning */
1100   nbpad = pinfos->gene.minsize - strlenstr;
1101   switch (pinfos->gene.align) {
1102     case NETWIB_PRIV_FMT_ALIGNTYPE_LEFT :
1103       nbpadl = 0;
1104       nbpadr = nbpad;
1105       break;
1106     case NETWIB_PRIV_FMT_ALIGNTYPE_CENTER :
1107       nbpadl = nbpad >> 1;
1108       nbpadr = nbpadl;
1109       if (nbpad&1) nbpadr++; /* if odd, one more at right */
1110       break;
1111     case NETWIB_PRIV_FMT_ALIGNTYPE_RIGHT :
1112       nbpadl = nbpad;
1113       nbpadr = 0;
1114       break;
1115   }
1116 
1117   /* generate string */
1118   ploc = localarray;
1119   pstr = str;
1120   while (nbpadl) {
1121     *ploc++ = pinfos->gene.padchar;
1122     nbpadl--;
1123   }
1124   while (strlenstr) {
1125     *ploc++ = *pstr++;
1126     strlenstr--;
1127   }
1128   while (nbpadr) {
1129     *ploc++ = pinfos->gene.padchar;
1130     nbpadr--;
1131   }
1132   *ploc = '\0';
1133 
1134   /* add it */
1135   ret = netwib_buf_append_string(localarray, pbuf);
1136   netwib__localarray_ifbuf_wipe(pbuf, localarray);
1137   return(ret);
1138 }
1139 
1140 /*-------------------------------------------------------------*/
netwib_priv_fmt_append(netwib_buf * pbuf,netwib_conststring fmt,va_list * pap,netwib_priv_fmtinfos * pinfos)1141 static netwib_err netwib_priv_fmt_append(netwib_buf *pbuf,
1142                                          netwib_conststring fmt,
1143                                          va_list *pap,
1144                                          netwib_priv_fmtinfos *pinfos)
1145 {
1146   netwib_char array[NETWIB_PRIV_FMT_ARR_SIZE];
1147   netwib_buf localbuf;
1148   netwib_string localstring;
1149   netwib_err ret;
1150 
1151   /* check if everything is fine for append */
1152   if (pinfos->geneset && pinfos->gene.skipfield) {
1153     netwib_er(netwib_priv_buf_append_vfmt_error2("an '*' is forbidden for append", fmt));
1154     return(NETWIB_ERR_PAFMT);
1155   }
1156 
1157   netwib_er(netwib_buf_init_ext_storagearraysizeof(array, &localbuf));
1158 
1159   /* append depending on type */
1160   switch(pinfos->fieldtype) {
1161     case NETWIB_PRIV_FMT_FIELDTYPE_END :
1162       netwib_er(netwib_priv_buf_append_vfmt_error2("a %$ is forbidden for append", fmt));
1163       return(NETWIB_ERR_PAFMT);
1164       break;
1165     case NETWIB_PRIV_FMT_FIELDTYPE_PERCENT :
1166       netwib_er(netwib_buf_append_byte('%', pbuf));
1167       /* leave here */
1168       return(NETWIB_ERR_OK);
1169       break;
1170     case NETWIB_PRIV_FMT_FIELDTYPE_C :
1171       {
1172         char c;
1173         /* Note : on some systems, there is a "cast increases required
1174            alignment size" warning here. It can be ignored */
1175         c = (char)va_arg(*pap, int);
1176         if (pinfos->geneset) {
1177           array[0] = c;
1178           array[1] = '\0';
1179           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1180         } else {
1181           netwib_er(netwib_buf_append_byte(c, pbuf));
1182         }
1183       }
1184       break;
1185     case NETWIB_PRIV_FMT_FIELDTYPE_BOOL :
1186       {
1187         netwib_bool b;
1188         netwib_conststring pstr;
1189         b = va_arg(*pap, netwib_bool);
1190         pstr = b?"true":"false";
1191         if (pinfos->specset) {
1192           switch(pinfos->spec.specbool.type) {
1193             case '0' : pstr = b?"1":"0"; break;
1194             case 'T' : pstr = b?"TRUE":"FALSE"; break;
1195             case 'y' : pstr = b?"yes":"no"; break;
1196             case 'Y' : pstr = b?"YES":"NO"; break;
1197             case 's' : pstr = b?"set":"unset"; break;
1198             case 'S' : pstr = b?"SET":"UNSET"; break;
1199           }
1200         }
1201         if (pinfos->geneset) {
1202           netwib_er(netwib_priv_fmt_append_gene(pstr, pinfos, pbuf));
1203         } else {
1204           netwib_er(netwib_buf_append_string(pstr, pbuf));
1205         }
1206       }
1207       break;
1208     case NETWIB_PRIV_FMT_FIELDTYPE_CMP :
1209       {
1210         netwib_cmp cmp;
1211         netwib_conststring pstr;
1212         cmp = va_arg(*pap, netwib_cmp);
1213         pstr = (cmp==NETWIB_CMP_LT)?"<":((cmp==NETWIB_CMP_EQ)?"=":">");
1214         if (pinfos->specset) {
1215           switch(pinfos->spec.specbool.type) {
1216             case '0' :
1217               pstr = (cmp==NETWIB_CMP_LT)?"-":((cmp==NETWIB_CMP_EQ)?"0":"+");
1218               break;
1219             case 'e' :
1220               pstr = (cmp==NETWIB_CMP_LT)?"lt":((cmp==NETWIB_CMP_EQ)?"eq":"gt");
1221               break;
1222           }
1223         }
1224         if (pinfos->geneset) {
1225           netwib_er(netwib_priv_fmt_append_gene(pstr, pinfos, pbuf));
1226         } else {
1227           netwib_er(netwib_buf_append_string(pstr, pbuf));
1228         }
1229       }
1230       break;
1231     case NETWIB_PRIV_FMT_FIELDTYPE_S :
1232       {
1233         netwib_char *pc;
1234         if (pinfos->specset && pinfos->spec.specs.useglob) {
1235           netwib_er(netwib_priv_buf_append_vfmt_error2("glob is forbidden for append", fmt));
1236           return(NETWIB_ERR_PAFMT);
1237         }
1238         pc = va_arg(*pap, netwib_char*);
1239         if (pinfos->geneset) {
1240           netwib_er(netwib_priv_fmt_append_gene(pc, pinfos, pbuf));
1241         } else {
1242           netwib_er(netwib_buf_append_string(pc, pbuf));
1243         }
1244       }
1245       break;
1246     case NETWIB_PRIV_FMT_FIELDTYPE_P :
1247       {
1248         netwib_priv_fmt_spec_uint su;
1249         void *p;
1250         p = va_arg(*pap, void*);
1251         array[0] = '0';
1252         array[1] = 'x';
1253         su.altformat = NETWIB_FALSE;
1254         su.minsize = 2*sizeof(void*);
1255         su.base = 16;
1256         netwib_er(netwib_priv_fmt_append_uintmax((netwib_uintptr)p, &su,
1257                                                  array+2));
1258         if (pinfos->geneset) {
1259           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1260         } else {
1261           netwib_er(netwib_buf_append_string(array, pbuf));
1262         }
1263       }
1264       break;
1265     case NETWIB_PRIV_FMT_FIELDTYPE_UINT32 :
1266     case NETWIB_PRIV_FMT_FIELDTYPE_UINT16 :
1267     case NETWIB_PRIV_FMT_FIELDTYPE_UINT8 :
1268     case NETWIB_PRIV_FMT_FIELDTYPE_BYTE :
1269     case NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX :
1270     case NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR :
1271       {
1272         netwib_uintmax ui=0;
1273         switch(pinfos->fieldtype) {
1274         case NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX :
1275           ui = va_arg(*pap, netwib_uintmax);
1276           break;
1277         case NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR :
1278           ui = va_arg(*pap, netwib_uintptr);
1279           break;
1280         default :
1281           ui = va_arg(*pap, netwib_uint32);
1282           break;
1283         }
1284         netwib_er(netwib_priv_fmt_append_uintmax(ui, &pinfos->spec.specuint,
1285                                                  array));
1286         if (pinfos->geneset) {
1287           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1288         } else {
1289           netwib_er(netwib_buf_append_string(array, pbuf));
1290         }
1291       }
1292       break;
1293     case NETWIB_PRIV_FMT_FIELDTYPE_UINT64 :
1294       {
1295         netwib_uint64 ui;
1296         ui = va_arg(*pap, netwib_uint64);
1297         netwib_er(netwib_priv_fmt_append_uint64(ui, &pinfos->spec.specuint,
1298                                                 array));
1299         if (pinfos->geneset) {
1300           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1301         } else {
1302           netwib_er(netwib_buf_append_string(array, pbuf));
1303         }
1304       }
1305       break;
1306     case NETWIB_PRIV_FMT_FIELDTYPE_INT32 :
1307     case NETWIB_PRIV_FMT_FIELDTYPE_INT16 :
1308     case NETWIB_PRIV_FMT_FIELDTYPE_INT8 :
1309     case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
1310     case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
1311       {
1312         netwib_intmax i=0;
1313         switch(pinfos->fieldtype) {
1314         case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
1315           i = va_arg(*pap, netwib_intmax);
1316           break;
1317         case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
1318           i = va_arg(*pap, netwib_intptr);
1319           break;
1320         default :
1321           i = va_arg(*pap, netwib_int32);
1322           break;
1323         }
1324         netwib_er(netwib_priv_fmt_append_intmax(i, &pinfos->spec.specint,
1325                                                 array));
1326         if (pinfos->geneset) {
1327           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1328         } else {
1329           netwib_er(netwib_buf_append_string(array, pbuf));
1330         }
1331       }
1332       break;
1333     case NETWIB_PRIV_FMT_FIELDTYPE_INT64 :
1334       {
1335         netwib_int64 i;
1336         i = va_arg(*pap, netwib_int64);
1337         netwib_er(netwib_priv_fmt_append_int64(i, &pinfos->spec.specint,
1338                                                array));
1339         if (pinfos->geneset) {
1340           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1341         } else {
1342           netwib_er(netwib_buf_append_string(array, pbuf));
1343         }
1344       }
1345       break;
1346     case NETWIB_PRIV_FMT_FIELDTYPE_BUF :
1347       {
1348         netwib_buf *pfmtbuf;
1349         if (pinfos->specset && pinfos->spec.specbuf.useglob) {
1350           netwib_er(netwib_priv_buf_append_vfmt_error2("glob is forbidden for append", fmt));
1351           return(NETWIB_ERR_PAFMT);
1352         }
1353         pfmtbuf = va_arg(*pap, netwib_buf*);
1354         /* do the transfer now because needed in netwib_priv_fmt_append_gene */
1355         netwib__buf_transfersensitive(pfmtbuf, pbuf);
1356         if (pinfos->geneset) {
1357           ret = netwib_constbuf_ref_string(pfmtbuf, &localstring);
1358           if (ret != NETWIB_ERR_OK) {
1359             netwib_er(netwib_buf_append_buf(pfmtbuf, &localbuf));
1360             netwib_er(netwib_buf_ref_string(&localbuf, &localstring));
1361           }
1362           netwib_er(netwib_priv_fmt_append_gene(localstring, pinfos, pbuf));
1363         } else {
1364           netwib_er(netwib_buf_append_buf(pfmtbuf, pbuf));
1365         }
1366       }
1367       break;
1368     case NETWIB_PRIV_FMT_FIELDTYPE_ETH :
1369       {
1370         netwib_eth *peth;
1371         peth = va_arg(*pap, netwib_eth*);
1372         netwib_er(netwib_priv_fmt_append_eth(peth, array));
1373         if (pinfos->geneset) {
1374           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1375         } else {
1376           netwib_er(netwib_buf_append_string(array, pbuf));
1377         }
1378       }
1379       break;
1380     case NETWIB_PRIV_FMT_FIELDTYPE_IP :
1381       {
1382         netwib_ip *pip;
1383         pip = va_arg(*pap, netwib_ip*);
1384         if (pinfos->geneset) {
1385           netwib_er(netwib_buf_append_ip(pip, NETWIB_IP_ENCODETYPE_IP,
1386                                          &localbuf));
1387           netwib_er(netwib_buf_ref_string(&localbuf, &localstring));
1388           netwib_er(netwib_priv_fmt_append_gene(localstring, pinfos, pbuf));
1389         } else {
1390           netwib_er(netwib_buf_append_ip(pip, NETWIB_IP_ENCODETYPE_IP,
1391                                          pbuf));
1392         }
1393       }
1394       break;
1395     case NETWIB_PRIV_FMT_FIELDTYPE_PORT :
1396       {
1397         netwib_priv_fmt_spec_uint su;
1398         netwib_port ui;
1399         ui = va_arg(*pap, netwib_port);
1400         su.altformat = NETWIB_FALSE;
1401         su.minsize = 0;
1402         su.base = 10;
1403         netwib_er(netwib_priv_fmt_append_uintmax(ui, &su, array));
1404         if (pinfos->geneset) {
1405           netwib_er(netwib_priv_fmt_append_gene(array, pinfos, pbuf));
1406         } else {
1407           netwib_er(netwib_buf_append_string(array, pbuf));
1408         }
1409       }
1410       break;
1411     case NETWIB_PRIV_FMT_FIELDTYPE_ETHS :
1412       {
1413         netwib_eths *peths;
1414         peths = va_arg(*pap, netwib_eths*);
1415         if (pinfos->geneset) {
1416           netwib_er(netwib_buf_append_eths(peths, &localbuf));
1417           netwib_er(netwib_buf_ref_string(&localbuf, &localstring));
1418           netwib_er(netwib_priv_fmt_append_gene(localstring, pinfos, pbuf));
1419         } else {
1420           netwib_er(netwib_buf_append_eths(peths, pbuf));
1421         }
1422       }
1423       break;
1424     case NETWIB_PRIV_FMT_FIELDTYPE_IPS :
1425       {
1426         netwib_ips *pips;
1427         pips = va_arg(*pap, netwib_ips*);
1428         if (pinfos->geneset) {
1429           netwib_er(netwib_buf_append_ips(pips, NETWIB_IPS_ENCODETYPE_BEST,
1430                                           &localbuf));
1431           netwib_er(netwib_buf_ref_string(&localbuf, &localstring));
1432           netwib_er(netwib_priv_fmt_append_gene(localstring, pinfos, pbuf));
1433         } else {
1434           netwib_er(netwib_buf_append_ips(pips, NETWIB_IPS_ENCODETYPE_BEST,
1435                                           pbuf));
1436         }
1437       }
1438       break;
1439     case NETWIB_PRIV_FMT_FIELDTYPE_PORTS :
1440       {
1441         netwib_ports *pports;
1442         pports = va_arg(*pap, netwib_ports*);
1443         if (pinfos->geneset) {
1444           netwib_er(netwib_buf_append_ports(pports, &localbuf));
1445           netwib_er(netwib_buf_ref_string(&localbuf, &localstring));
1446           netwib_er(netwib_priv_fmt_append_gene(localstring, pinfos, pbuf));
1447         } else {
1448           netwib_er(netwib_buf_append_ports(pports, pbuf));
1449         }
1450       }
1451       break;
1452   }
1453 
1454   netwib_er(netwib_buf_close(&localbuf));
1455 
1456   return(NETWIB_ERR_OK);
1457 }
1458 
1459 /*-------------------------------------------------------------*/
netwib_priv_buf_append_vfmt(netwib_buf * pbuf,netwib_conststring fmt,va_list * pap)1460 netwib_err netwib_priv_buf_append_vfmt(netwib_buf *pbuf,
1461                                        netwib_conststring fmt,
1462                                        va_list *pap)
1463 {
1464   netwib_conststring pfmt, ppercent;
1465   netwib_priv_fmtinfos infos;
1466   netwib_uint32 savedsize=0;
1467   netwib_err ret;
1468 
1469   /* save position in case of error */
1470   if (pbuf != NULL) {
1471     savedsize = netwib__buf_ref_data_size(pbuf);
1472   }
1473 
1474   /* main loop */
1475   pfmt = fmt;
1476   ret = NETWIB_ERR_LOINTERNALERROR;
1477   while (NETWIB_TRUE) {
1478     /* search '%' */
1479     ppercent = netwib_c_strchr(pfmt, '%');
1480     if (ppercent == NULL) {
1481       /* not found, so copy the end of format */
1482       ret = netwib_buf_append_string(pfmt, pbuf);
1483       break;
1484     } else {
1485       /* first append data before '%' */
1486       ret = netwib_buf_append_data((netwib_constdata)pfmt, ppercent-pfmt,
1487                                    pbuf);
1488       if (ret != NETWIB_ERR_OK) {
1489         break;
1490       }
1491       /* analyze format and complete */
1492       pfmt = ppercent + 1;
1493       ret = netwib_priv_fmt_analyze(pfmt, &infos);
1494       if (ret != NETWIB_ERR_OK) {
1495         break;
1496       }
1497       ret = netwib_priv_fmt_append(pbuf, pfmt, pap, &infos);
1498       if (ret != NETWIB_ERR_OK) {
1499         break;
1500       }
1501       pfmt += infos.skipsize;
1502     }
1503   }
1504 
1505   /* on error, restore first pos */
1506   if (ret != NETWIB_ERR_OK) {
1507     if (pbuf != NULL) {
1508       pbuf->endoffset = pbuf->beginoffset + savedsize;
1509     }
1510   }
1511 
1512   /* leave */
1513   return(ret);
1514 }
1515 
1516 /*-------------------------------------------------------------*/
netwib_buf_append_fmt(netwib_buf * pbuf,netwib_conststring fmt,...)1517 netwib_err netwib_buf_append_fmt(netwib_buf *pbuf,
1518                                  netwib_conststring fmt,
1519                                  ...)
1520 {
1521   va_list ap;
1522   netwib_err ret;
1523 
1524   va_start(ap, fmt);
1525   ret = netwib_priv_buf_append_vfmt(pbuf, fmt, &ap);
1526   va_end(ap);
1527   return(ret);
1528 }
1529 
1530 
1531 /*-------------------------------------------------------------*/
1532 /*-------------------------------------------------------------*/
1533 /*-------------------------------------------------------------*/
1534 /*-------------------------------------------------------------*/
1535 
1536 /*-------------------------------------------------------------*/
1537 typedef struct {
1538   netwib_priv_fmtinfos fmtinfos;
1539   netwib_ptr ptr;
1540 } netwib_priv_fmt_scanitem;
1541 
1542 /*-------------------------------------------------------------*/
netwib_priv_fmt_regexp(netwib_buf * pbuf,netwib_priv_fmtinfos * pinfos)1543 static netwib_err netwib_priv_fmt_regexp(netwib_buf *pbuf,
1544                                          netwib_priv_fmtinfos *pinfos)
1545 {
1546   netwib_bool skipfield;
1547 
1548   if (pinfos->geneset) {
1549     if (pinfos->gene.minsize) {
1550       if (pinfos->gene.align != NETWIB_PRIV_FMT_ALIGNTYPE_LEFT) {
1551         netwib_byte array[4];
1552         array[0] = '[';
1553         array[1] = pinfos->gene.padchar;
1554         array[2] = ']';
1555         array[3] = '*';
1556         netwib_er(netwib_buf_append_data(array, 4, pbuf));
1557       }
1558     }
1559   }
1560 
1561   skipfield = NETWIB_FALSE;
1562   if (pinfos->geneset) {
1563     if (pinfos->gene.skipfield) {
1564       skipfield = NETWIB_TRUE;
1565     }
1566   }
1567 
1568   if (!skipfield) {
1569     /* those cases can easily be encapsulated by parenthesis */
1570     switch(pinfos->fieldtype) {
1571       case NETWIB_PRIV_FMT_FIELDTYPE_C :
1572       case NETWIB_PRIV_FMT_FIELDTYPE_P :
1573       case NETWIB_PRIV_FMT_FIELDTYPE_INT32 :
1574       case NETWIB_PRIV_FMT_FIELDTYPE_INT16 :
1575       case NETWIB_PRIV_FMT_FIELDTYPE_INT8 :
1576       case NETWIB_PRIV_FMT_FIELDTYPE_INT64 :
1577       case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
1578       case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
1579       case NETWIB_PRIV_FMT_FIELDTYPE_BOOL :
1580       case NETWIB_PRIV_FMT_FIELDTYPE_CMP :
1581       case NETWIB_PRIV_FMT_FIELDTYPE_ETH :
1582       case NETWIB_PRIV_FMT_FIELDTYPE_IP :
1583       case NETWIB_PRIV_FMT_FIELDTYPE_PORT :
1584       case NETWIB_PRIV_FMT_FIELDTYPE_ETHS :
1585       case NETWIB_PRIV_FMT_FIELDTYPE_IPS :
1586       case NETWIB_PRIV_FMT_FIELDTYPE_PORTS :
1587         netwib_er(netwib_buf_append_byte('(', pbuf));
1588         break;
1589       default :
1590         break;
1591     }
1592   }
1593 
1594   switch(pinfos->fieldtype) {
1595     case NETWIB_PRIV_FMT_FIELDTYPE_PERCENT :
1596       netwib_er(netwib_buf_append_string("[%]", pbuf));
1597       break;
1598     case NETWIB_PRIV_FMT_FIELDTYPE_END :
1599       netwib_er(netwib_buf_append_byte('$', pbuf));
1600       break;
1601     case NETWIB_PRIV_FMT_FIELDTYPE_C :
1602       netwib_er(netwib_buf_append_byte('.', pbuf));
1603       break;
1604     case NETWIB_PRIV_FMT_FIELDTYPE_S :
1605       if (pinfos->specset && pinfos->spec.specs.useglob) {
1606         if (skipfield) {
1607           netwib_er(netwib_buf_append_string(".+", pbuf));
1608         } else {
1609           netwib_er(netwib_buf_append_string("(.+)", pbuf));
1610         }
1611       } else {
1612         if (skipfield) {
1613           netwib_er(netwib_buf_append_string("[ \t]*[^ \t]+[ \t]*", pbuf));
1614         } else {
1615           netwib_er(netwib_buf_append_string("[ \t]*([^ \t]+)[ \t]*", pbuf));
1616         }
1617       }
1618       break;
1619     case NETWIB_PRIV_FMT_FIELDTYPE_BUF :
1620       if (pinfos->specset && pinfos->spec.specbuf.useglob) {
1621         if (skipfield) {
1622           netwib_er(netwib_buf_append_string(".+", pbuf));
1623         } else {
1624           netwib_er(netwib_buf_append_string("(.+)", pbuf));
1625         }
1626       } else {
1627         if (skipfield) {
1628           netwib_er(netwib_buf_append_string("[ \t]*[^ \t]+[ \t]*", pbuf));
1629         } else {
1630           netwib_er(netwib_buf_append_string("[ \t]*([^ \t]+)[ \t]*", pbuf));
1631         }
1632       }
1633       break;
1634     case NETWIB_PRIV_FMT_FIELDTYPE_P :
1635       netwib_er(netwib_buf_append_string("[0-9a-fA-Fx]+", pbuf));
1636       break;
1637     case NETWIB_PRIV_FMT_FIELDTYPE_UINT32 :
1638     case NETWIB_PRIV_FMT_FIELDTYPE_UINT16 :
1639     case NETWIB_PRIV_FMT_FIELDTYPE_UINT8 :
1640     case NETWIB_PRIV_FMT_FIELDTYPE_UINT64 :
1641     case NETWIB_PRIV_FMT_FIELDTYPE_BYTE :
1642     case NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX :
1643     case NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR :
1644       if (pinfos->specset) {
1645         if (!skipfield) {
1646           netwib_er(netwib_buf_append_byte('(', pbuf));
1647         }
1648         switch(pinfos->spec.specuint.base) {
1649           case 2 :
1650             netwib_er(netwib_buf_append_string("b?[0-1]+", pbuf));
1651             break;
1652           case 8 :
1653             netwib_er(netwib_buf_append_string("[0-7+]+", pbuf));
1654             break;
1655           case 10 :
1656             netwib_er(netwib_buf_append_string("[0-9+]+", pbuf));
1657             break;
1658           case 16 :
1659           case 17 :
1660             netwib_er(netwib_buf_append_string("[0-9a-fA-Fx+]+", pbuf));
1661             break;
1662         }
1663         if (!skipfield) {
1664           netwib_er(netwib_buf_append_byte(')', pbuf));
1665         }
1666       } else {
1667         if (skipfield) {
1668           netwib_er(netwib_buf_append_string("[0-9a-fA-Fx+]+", pbuf));
1669         } else {
1670           netwib_er(netwib_buf_append_string("([0-9a-fA-Fx+]+)", pbuf));
1671         }
1672       }
1673       break;
1674     case NETWIB_PRIV_FMT_FIELDTYPE_INT32 :
1675     case NETWIB_PRIV_FMT_FIELDTYPE_INT16 :
1676     case NETWIB_PRIV_FMT_FIELDTYPE_INT8 :
1677     case NETWIB_PRIV_FMT_FIELDTYPE_INT64 :
1678     case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
1679     case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
1680       netwib_er(netwib_buf_append_string("[0-9+-]+", pbuf));
1681       break;
1682     case NETWIB_PRIV_FMT_FIELDTYPE_BOOL :
1683       if (pinfos->specset) {
1684         switch (pinfos->spec.specbool.type) {
1685           case '0' :
1686             netwib_er(netwib_buf_append_string("[01]", pbuf));
1687             break;
1688           case 't' :
1689             netwib_er(netwib_buf_append_string("[truefals]+", pbuf));
1690             break;
1691           case 'T' :
1692             netwib_er(netwib_buf_append_string("[TRUEFALS]+", pbuf));
1693             break;
1694           case 'y' :
1695             netwib_er(netwib_buf_append_string("[yesno]+", pbuf));
1696             break;
1697           case 'Y' :
1698             netwib_er(netwib_buf_append_string("[YESNO]+", pbuf));
1699             break;
1700           case 's' :
1701             netwib_er(netwib_buf_append_string("[unset]+", pbuf));
1702             break;
1703           case 'S' :
1704             netwib_er(netwib_buf_append_string("[UNSET]+", pbuf));
1705             break;
1706         }
1707       } else {
1708         netwib_er(netwib_buf_append_string("[01enorstuyENORSTUY]+", pbuf));
1709       }
1710       break;
1711     case NETWIB_PRIV_FMT_FIELDTYPE_CMP :
1712       if (pinfos->specset) {
1713         switch (pinfos->spec.speccmp.type) {
1714           case '=' :
1715             netwib_er(netwib_buf_append_string("[<=>]", pbuf));
1716             break;
1717           case '0' :
1718             netwib_er(netwib_buf_append_string("[+0-]", pbuf));
1719             break;
1720           case 'e' :
1721             netwib_er(netwib_buf_append_string("[egl][qt]", pbuf));
1722             break;
1723         }
1724       } else {
1725         netwib_er(netwib_buf_append_string("[<=>eglqt+0-]+", pbuf));
1726       }
1727       break;
1728     case NETWIB_PRIV_FMT_FIELDTYPE_ETH :
1729       netwib_er(netwib_buf_append_string("[0-9a-fA-F][0-9a-fA-F]?:[0-9a-fA-F][0-9a-fA-F]?:[0-9a-fA-F][0-9a-fA-F]?:[0-9a-fA-F][0-9a-fA-F]?:[0-9a-fA-F][0-9a-fA-F]?:[0-9a-fA-F][0-9a-fA-F]?", pbuf));
1730       break;
1731     case NETWIB_PRIV_FMT_FIELDTYPE_IP :
1732       netwib_er(netwib_buf_append_string("[0-9a-fA-F.:]+", pbuf));
1733       break;
1734     case NETWIB_PRIV_FMT_FIELDTYPE_PORT :
1735       netwib_er(netwib_buf_append_string("[0-9]+", pbuf));
1736       break;
1737     case NETWIB_PRIV_FMT_FIELDTYPE_ETHS :
1738       netwib_er(netwib_buf_append_string("[0-9a-fA-F:,-]+", pbuf));
1739       break;
1740     case NETWIB_PRIV_FMT_FIELDTYPE_IPS :
1741       netwib_er(netwib_buf_append_string("[0-9.:,-]+", pbuf));
1742       break;
1743     case NETWIB_PRIV_FMT_FIELDTYPE_PORTS :
1744       netwib_er(netwib_buf_append_string("[0-9,-]+", pbuf));
1745       break;
1746   }
1747 
1748   if (!skipfield) {
1749     switch(pinfos->fieldtype) {
1750       case NETWIB_PRIV_FMT_FIELDTYPE_C :
1751       case NETWIB_PRIV_FMT_FIELDTYPE_P :
1752       case NETWIB_PRIV_FMT_FIELDTYPE_INT32 :
1753       case NETWIB_PRIV_FMT_FIELDTYPE_INT16 :
1754       case NETWIB_PRIV_FMT_FIELDTYPE_INT8 :
1755       case NETWIB_PRIV_FMT_FIELDTYPE_INT64 :
1756       case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
1757       case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
1758       case NETWIB_PRIV_FMT_FIELDTYPE_BOOL :
1759       case NETWIB_PRIV_FMT_FIELDTYPE_CMP :
1760       case NETWIB_PRIV_FMT_FIELDTYPE_ETH :
1761       case NETWIB_PRIV_FMT_FIELDTYPE_IP :
1762       case NETWIB_PRIV_FMT_FIELDTYPE_PORT :
1763       case NETWIB_PRIV_FMT_FIELDTYPE_ETHS :
1764       case NETWIB_PRIV_FMT_FIELDTYPE_IPS :
1765       case NETWIB_PRIV_FMT_FIELDTYPE_PORTS :
1766         netwib_er(netwib_buf_append_byte(')', pbuf));
1767         break;
1768       default :
1769         break;
1770     }
1771   }
1772 
1773   if (pinfos->geneset) {
1774     if (pinfos->gene.minsize) {
1775       if (pinfos->gene.align != NETWIB_PRIV_FMT_ALIGNTYPE_RIGHT) {
1776         netwib_byte array[4];
1777         array[0] = '[';
1778         array[1] = pinfos->gene.padchar;
1779         array[2] = ']';
1780         array[3] = '*';
1781         netwib_er(netwib_buf_append_data(array, 4, pbuf));
1782       }
1783     }
1784   }
1785 
1786   return(NETWIB_ERR_OK);
1787 }
1788 
1789 /*-------------------------------------------------------------*/
netwib_priv_fmt_decode_uint32(netwib_constbuf * pbuf,netwib_uint32 base,netwib_uint32 * pnumber)1790 static netwib_err netwib_priv_fmt_decode_uint32(netwib_constbuf *pbuf,
1791                                                 netwib_uint32 base,
1792                                                 netwib_uint32 *pnumber)
1793 {
1794   netwib_string str;
1795   netwib_uintmax number;
1796   char *p;
1797 
1798   /* obtain a reference to the string */
1799   netwib__constbuf_ref_string(pbuf, str, bufstorage,
1800                               netwib_priv_fmt_decode_uint32(&bufstorage, base, pnumber));
1801 
1802   /* special case */
1803   if (*str == '\0') {
1804     return(NETWIB_ERR_PAINT);
1805   }
1806 
1807   /* base 2 starting with 'b' is not supported by strtoul */
1808   if (base == 2 && *str == 'b') {
1809     str++;
1810   }
1811 
1812   /* find number */
1813   number = strtoul(str, &p, base);
1814   if (*p != '\0') {
1815     return(NETWIB_ERR_PAINT);
1816   }
1817 
1818   /* number is too big */
1819   if (number == ULONG_MAX && errno == ERANGE) {
1820     errno = 0;
1821     return(NETWIB_ERR_PATOOHIGH);
1822   }
1823 #if NETWIB_INTMAX_BITS == 64
1824   if (number > 0xFFFFFFFFu) {
1825     return(NETWIB_ERR_PATOOHIGH);
1826   }
1827 #endif
1828 
1829   if (pnumber != NULL) *pnumber = (netwib_uint32)number;
1830   return(NETWIB_ERR_OK);
1831 }
1832 
1833 /*-------------------------------------------------------------*/
netwib_priv_fmt_decode_int32(netwib_constbuf * pbuf,netwib_int32 * pnumber)1834 static netwib_err netwib_priv_fmt_decode_int32(netwib_constbuf *pbuf,
1835                                                netwib_int32 *pnumber)
1836 {
1837   netwib_string str;
1838   netwib_intmax number;
1839   char *p;
1840 
1841   /* obtain a reference to the string */
1842   netwib__constbuf_ref_string(pbuf, str, bufstorage,
1843                               netwib_priv_fmt_decode_int32(&bufstorage, pnumber));
1844 
1845   /* special case */
1846   if (*str == '\0') {
1847     return(NETWIB_ERR_PAINT);
1848   }
1849 
1850   /* find number */
1851   number = strtol(str, &p, 10);
1852   if (*p != '\0') {
1853     return(NETWIB_ERR_PAINT);
1854   }
1855 
1856   /* number is too big */
1857   if (errno == ERANGE) {
1858     errno = 0;
1859     if (number == LONG_MAX)
1860       return(NETWIB_ERR_PATOOHIGH);
1861     else if (number == LONG_MIN)
1862       return(NETWIB_ERR_PATOOLOW);
1863   }
1864 #if NETWIB_INTMAX_BITS == 64
1865   if (number > 0 && number > 0x7FFFFFFF) {
1866     return(NETWIB_ERR_PATOOHIGH);
1867   }
1868   if (number < 0 && number < -0x7FFFFFFF-1) {
1869     return(NETWIB_ERR_PATOOLOW);
1870   }
1871 #endif
1872 
1873   if (pnumber != NULL) *pnumber = (netwib_int32)number;
1874   return(NETWIB_ERR_OK);
1875 }
1876 
1877 /*-------------------------------------------------------------*/
netwib_priv_fmt_decode_uint64(netwib_constbuf * pbuf,netwib_uint32 base,netwib_uint64 * pnumber)1878 static netwib_err netwib_priv_fmt_decode_uint64(netwib_constbuf *pbuf,
1879                                                 netwib_uint32 base,
1880                                                 netwib_uint64 *pnumber)
1881 {
1882   netwib_uint64 base64, number, number2, c64;
1883   netwib_uint32 c32;
1884   netwib_string pc;
1885   netwib_char c;
1886 
1887   /* obtain a reference to the string */
1888   netwib__constbuf_ref_string(pbuf, pc, bufstorage,
1889                               netwib_priv_fmt_decode_uint64(&bufstorage, base, pnumber));
1890 
1891   /* skip useless characters*/
1892   if (*pc == '+') {
1893     pc++;
1894   }
1895   switch(base) {
1896   case 2 :
1897     if (*pc == 'b') {
1898       pc++;
1899     }
1900     break;
1901   case 16 :
1902     if (*pc == '0' && *(pc+1) == 'x') {
1903       pc += 2;
1904     }
1905     break;
1906   case 0 : /* need to guess ; by default 10 (note: no way to detect binary) */
1907     base = 10;
1908     if (*pc == '0') {
1909       if (*(pc+1) == 'x') {
1910         pc += 2;
1911         base = 16;
1912       } else {
1913         /* do not increment pc to leave the '0' */
1914         base = 8;
1915       }
1916     }
1917     break;
1918   }
1919   if (*pc == '\0') {
1920     return(NETWIB_ERR_PAINT);
1921   }
1922 
1923   /* loop and store in number */
1924   netwib__uint64_init_uint32(0, number);
1925   netwib__uint64_init_uint32(base, base64);
1926   while(NETWIB_TRUE) {
1927     c = *pc++;
1928     if (c == '\0') {
1929       break;
1930     }
1931     netwib_c2_cto16_if(c, c32) else {
1932       return(NETWIB_ERR_PAINT);
1933     }
1934     if (c32 >= base) {
1935       return(NETWIB_ERR_PAINT);
1936     }
1937     netwib__uint64_init_uint32(c32, c64);
1938     netwib__uint64_mul(number, base64, &number2);
1939     netwib__uint64_add(number2, c64, number2);
1940     if (netwib__uint64_cmp_lt(number2, number)) {
1941       /* an overflow occurred */
1942       return(NETWIB_ERR_PAINT);
1943     }
1944     number = number2;
1945   }
1946 
1947   if (pnumber != NULL) *pnumber = number;
1948   return(NETWIB_ERR_OK);
1949 }
1950 
1951 /*-------------------------------------------------------------*/
netwib_priv_fmt_decode_int64(netwib_constbuf * pbuf,netwib_int64 * pnumber)1952 static netwib_err netwib_priv_fmt_decode_int64(netwib_constbuf *pbuf,
1953                                                netwib_int64 *pnumber)
1954 {
1955   netwib_buf buf;
1956   netwib_data data;
1957   netwib_uint32 datasize;
1958   netwib_uint64 ui64, maxint64;
1959   netwib_bool ispos;
1960 
1961   datasize = netwib__buf_ref_data_size(pbuf);
1962   if (datasize == 0) {
1963     return(NETWIB_ERR_PAINT);
1964   }
1965   data = netwib__buf_ref_data_ptr(pbuf);
1966 
1967   /* check if a sign is present */
1968   ispos = NETWIB_TRUE;
1969   switch(*data) {
1970   case '-' :
1971     ispos = NETWIB_FALSE;
1972     data++;
1973     datasize--;
1974     break;
1975   case '+' :
1976     data++;
1977     datasize--;
1978     break;
1979   }
1980 
1981   /* decode an unsigned */
1982   netwib_er(netwib_buf_init_ext_arrayfilled(data, datasize, &buf));
1983   netwib_er(netwib_priv_fmt_decode_uint64(&buf, 10, &ui64));
1984   netwib__uint64_init_32(0x80000000u, 0, maxint64);
1985   if (ispos) {
1986     if (netwib__uint64_cmp_gt(ui64, maxint64)) {
1987       return(NETWIB_ERR_PATOOHIGH);
1988     }
1989     *pnumber = ui64;
1990   } else {
1991     if (netwib__uint64_cmp_gt(ui64, maxint64)) {
1992       return(NETWIB_ERR_PATOOLOW);
1993     }
1994     netwib__int64_neg(ui64, *pnumber);
1995   }
1996 
1997   return(NETWIB_ERR_OK);
1998 }
1999 
2000 /*-------------------------------------------------------------*/
netwib_priv_fmt_decode_bool(netwib_constbuf * pbuf,netwib_bool * pb)2001 static netwib_err netwib_priv_fmt_decode_bool(netwib_constbuf *pbuf,
2002                                               netwib_bool *pb)
2003 {
2004   netwib_data data;
2005   netwib_uint32 datasize;
2006   netwib_char firstchar;
2007   netwib_bool b;
2008 
2009   datasize = netwib__buf_ref_data_size(pbuf);
2010   if (datasize == 0) {
2011     return(NETWIB_ERR_PAINT);
2012   }
2013   data = netwib__buf_ref_data_ptr(pbuf);
2014 
2015 #define netwib__priv_fmt_decode_bool_cmp(txt,val) if (!netwib_c_memcasecmp(data, (netwib_constdata)txt, datasize)) { b = val; break; }
2016   firstchar = data[0];
2017   switch(firstchar) {
2018   case '0' :
2019     if (datasize == 1) {
2020       b = NETWIB_FALSE;
2021       break;
2022     }
2023     return(NETWIB_ERR_PAINT);
2024     break;
2025   case '1' :
2026     if (datasize == 1) {
2027       b = NETWIB_TRUE;
2028       break;
2029     }
2030     return(NETWIB_ERR_PAINT);
2031     break;
2032   case 'f' :
2033   case 'F' :
2034     if (datasize == 5) {
2035       netwib__priv_fmt_decode_bool_cmp("false", NETWIB_FALSE);
2036     }
2037     return(NETWIB_ERR_PAINT);
2038     break;
2039   case 'n' :
2040   case 'N' :
2041     if (datasize == 2) {
2042       netwib__priv_fmt_decode_bool_cmp("no", NETWIB_FALSE);
2043     }
2044     return(NETWIB_ERR_PAINT);
2045     break;
2046   case 's' :
2047   case 'S' :
2048     if (datasize == 3) {
2049       netwib__priv_fmt_decode_bool_cmp("set", NETWIB_TRUE);
2050     }
2051     return(NETWIB_ERR_PAINT);
2052     break;
2053   case 't' :
2054   case 'T' :
2055     if (datasize == 4) {
2056       netwib__priv_fmt_decode_bool_cmp("true", NETWIB_TRUE);
2057     }
2058     return(NETWIB_ERR_PAINT);
2059     break;
2060   case 'u' :
2061   case 'U' :
2062     if (datasize == 5) {
2063       netwib__priv_fmt_decode_bool_cmp("unset", NETWIB_FALSE);
2064     }
2065     return(NETWIB_ERR_PAINT);
2066     break;
2067   case 'y' :
2068   case 'Y' :
2069     if (datasize == 3) {
2070       netwib__priv_fmt_decode_bool_cmp("yes", NETWIB_TRUE);
2071     }
2072     return(NETWIB_ERR_PAINT);
2073     break;
2074   default :
2075     return(NETWIB_ERR_PAINT);
2076   }
2077 
2078   if (pb != NULL) *pb = b;
2079   return(NETWIB_ERR_OK);
2080 }
2081 
2082 /*-------------------------------------------------------------*/
netwib_priv_fmt_decode_cmp(netwib_constbuf * pbuf,netwib_cmp * pcmp)2083 static netwib_err netwib_priv_fmt_decode_cmp(netwib_constbuf *pbuf,
2084                                              netwib_cmp *pcmp)
2085 {
2086   netwib_data data;
2087   netwib_uint32 datasize;
2088   netwib_char firstchar;
2089   netwib_cmp cmp;
2090 
2091   datasize = netwib__buf_ref_data_size(pbuf);
2092   if (datasize == 0) {
2093     return(NETWIB_ERR_PAINT);
2094   }
2095   data = netwib__buf_ref_data_ptr(pbuf);
2096 
2097   firstchar = data[0];
2098   switch(firstchar) {
2099   case '<' :
2100     if (datasize == 1) {
2101       cmp = NETWIB_CMP_LT;
2102       break;
2103     }
2104     return(NETWIB_ERR_PAINT);
2105     break;
2106   case '=' :
2107     if (datasize == 1) {
2108       cmp = NETWIB_CMP_EQ;
2109       break;
2110     }
2111     return(NETWIB_ERR_PAINT);
2112     break;
2113   case '>' :
2114     if (datasize == 1) {
2115       cmp = NETWIB_CMP_GT;
2116       break;
2117     }
2118     return(NETWIB_ERR_PAINT);
2119     break;
2120   case '-' :
2121     if (datasize == 1) {
2122       cmp = NETWIB_CMP_LT;
2123       break;
2124     }
2125     return(NETWIB_ERR_PAINT);
2126     break;
2127   case '0' :
2128     if (datasize == 1) {
2129       cmp = NETWIB_CMP_EQ;
2130       break;
2131     }
2132     return(NETWIB_ERR_PAINT);
2133     break;
2134   case '+' :
2135     if (datasize == 1) {
2136       cmp = NETWIB_CMP_GT;
2137       break;
2138     }
2139     return(NETWIB_ERR_PAINT);
2140     break;
2141   case 'e' :
2142     if (datasize == 2 && data[1] == 'q') {
2143       cmp = NETWIB_CMP_EQ;
2144       break;
2145     }
2146     return(NETWIB_ERR_PAINT);
2147     break;
2148   case 'g' :
2149     if (datasize == 2 && data[1] == 't') {
2150       cmp = NETWIB_CMP_GT;
2151       break;
2152     }
2153     return(NETWIB_ERR_PAINT);
2154     break;
2155   case 'l' :
2156     if (datasize == 2 && data[1] == 't') {
2157       cmp = NETWIB_CMP_LT;
2158       break;
2159     }
2160     return(NETWIB_ERR_PAINT);
2161     break;
2162   default :
2163     return(NETWIB_ERR_PAINT);
2164   }
2165 
2166   if (pcmp != NULL) *pcmp = cmp;
2167   return(NETWIB_ERR_OK);
2168 }
2169 
2170 /*-------------------------------------------------------------*/
netwib_priv_fmt_decode(netwib_constbuf * pbuf,const netwib_priv_fmt_scanitem * pscanitem)2171 static netwib_err netwib_priv_fmt_decode(netwib_constbuf *pbuf,
2172                                          const netwib_priv_fmt_scanitem *pscanitem)
2173 {
2174   netwib_uint64 ui64;
2175   netwib_uint32 ui32=0;
2176   netwib_int64 i64;
2177   netwib_int32 i32=0;
2178   netwib_uintptr uiptr=0;
2179   netwib_err ret;
2180 
2181   if (pscanitem->ptr == NULL) {
2182     return(NETWIB_ERR_OK);
2183   }
2184 
2185   switch(pscanitem->fmtinfos.fieldtype) {
2186     case NETWIB_PRIV_FMT_FIELDTYPE_PERCENT :
2187       return(NETWIB_ERR_LOINTERNALERROR);
2188       break;
2189     case NETWIB_PRIV_FMT_FIELDTYPE_C :
2190       {
2191         netwib_char *pc = (netwib_char *)pscanitem->ptr;
2192         *pc = *netwib__buf_ref_data_ptr(pbuf);
2193       }
2194       return(NETWIB_ERR_OK);
2195       break;
2196     case NETWIB_PRIV_FMT_FIELDTYPE_S :
2197       {
2198         netwib_char *pc = (netwib_char *)pscanitem->ptr;
2199         netwib_c_memcpy(pc, netwib__buf_ref_data_ptr(pbuf),
2200                         netwib__buf_ref_data_size(pbuf));
2201         pc[netwib__buf_ref_data_size(pbuf)] = '\0';
2202       }
2203       return(NETWIB_ERR_OK);
2204       break;
2205     case NETWIB_PRIV_FMT_FIELDTYPE_BUF :
2206       {
2207         netwib_buf *p = (netwib_buf *)pscanitem->ptr;
2208         netwib_er(netwib_buf_append_buf(pbuf, p));
2209       }
2210       return(NETWIB_ERR_OK);
2211       break;
2212     default :
2213       break;
2214   }
2215 
2216   /* initialize for integer conversions */
2217   ret = NETWIB_ERR_OK;
2218   netwib__uint64_init_uint32(0, ui64);
2219   netwib__int64_init_int32(0, i64);
2220   switch(pscanitem->fmtinfos.fieldtype) {
2221     case NETWIB_PRIV_FMT_FIELDTYPE_UINT32 :
2222     case NETWIB_PRIV_FMT_FIELDTYPE_UINT16 :
2223     case NETWIB_PRIV_FMT_FIELDTYPE_UINT8 :
2224     case NETWIB_PRIV_FMT_FIELDTYPE_BYTE :
2225       {
2226         netwib_uint32 base;
2227         base = 0;
2228         if (pscanitem->fmtinfos.specset) {
2229           base = pscanitem->fmtinfos.spec.specuint.base;
2230           if (base == 17) base = 16;
2231         }
2232         ret = netwib_priv_fmt_decode_uint32(pbuf, base, &ui32);
2233       }
2234       break;
2235     case NETWIB_PRIV_FMT_FIELDTYPE_UINT64 :
2236     case NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX :
2237     case NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR :
2238       {
2239         netwib_uint32 base;
2240         base = 0;
2241         if (pscanitem->fmtinfos.specset) {
2242           base = pscanitem->fmtinfos.spec.specuint.base;
2243           if (base == 17) base = 16;
2244         }
2245         ret = netwib_priv_fmt_decode_uint64(pbuf, base, &ui64);
2246       }
2247       break;
2248     case NETWIB_PRIV_FMT_FIELDTYPE_P :
2249 #if NETWIB_INTPTR_BITS == 64
2250       ret = netwib_priv_fmt_decode_uint64(pbuf, 16, &ui64);
2251       if (ret == NETWIB_ERR_OK) {
2252         netwib__uintptr_init_uint64(ui64, uiptr);
2253       }
2254 #else
2255       ret = netwib_priv_fmt_decode_uint32(pbuf, 16,
2256                                           (netwib_uint32*)&uiptr);
2257 #endif
2258       break;
2259     case NETWIB_PRIV_FMT_FIELDTYPE_INT32 :
2260     case NETWIB_PRIV_FMT_FIELDTYPE_INT16 :
2261     case NETWIB_PRIV_FMT_FIELDTYPE_INT8 :
2262       ret = netwib_priv_fmt_decode_int32(pbuf, &i32);
2263       break;
2264     case NETWIB_PRIV_FMT_FIELDTYPE_INT64 :
2265     case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
2266     case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
2267       ret = netwib_priv_fmt_decode_int64(pbuf, &i64);
2268       break;
2269     default :
2270       /* ui does not need to be initialized */
2271       break;
2272   }
2273 
2274   if (ret == NETWIB_ERR_OK) {
2275     switch(pscanitem->fmtinfos.fieldtype) {
2276     case NETWIB_PRIV_FMT_FIELDTYPE_P :
2277       {
2278         netwib_ptr *p = (netwib_ptr *)pscanitem->ptr;
2279         *p = (netwib_ptr)uiptr;
2280       }
2281       break;
2282     case NETWIB_PRIV_FMT_FIELDTYPE_UINT32 :
2283       {
2284         netwib_uint32 *p = (netwib_uint32 *)pscanitem->ptr;
2285         *p = ui32;
2286       }
2287       break;
2288     case NETWIB_PRIV_FMT_FIELDTYPE_UINT16 :
2289       {
2290         netwib_uint16 *p = (netwib_uint16 *)pscanitem->ptr;
2291         if (ui32 > 0xFFFF) {
2292           ret = NETWIB_ERR_PATOOHIGH;
2293         } else {
2294           *p = (netwib_uint16)ui32;
2295         }
2296       }
2297       break;
2298     case NETWIB_PRIV_FMT_FIELDTYPE_UINT8 :
2299       {
2300         netwib_uint8 *p = (netwib_uint8 *)pscanitem->ptr;
2301         if (ui32 > 0xFF) {
2302           ret = NETWIB_ERR_PATOOHIGH;
2303         } else {
2304           *p = (netwib_uint8)ui32;
2305         }
2306       }
2307       break;
2308     case NETWIB_PRIV_FMT_FIELDTYPE_BYTE :
2309       {
2310         netwib_byte *p = (netwib_byte *)pscanitem->ptr;
2311         if (ui32 > 0xFF) {
2312           ret = NETWIB_ERR_PATOOHIGH;
2313         } else {
2314           *p = (netwib_byte)ui32;
2315         }
2316       }
2317       break;
2318     case NETWIB_PRIV_FMT_FIELDTYPE_UINT64 :
2319       {
2320         netwib_uint64 *p = (netwib_uint64 *)pscanitem->ptr;
2321         *p = ui64;
2322       }
2323       break;
2324     case NETWIB_PRIV_FMT_FIELDTYPE_UINTMAX :
2325       netwib__uintmax_init_uint64(ui64, *(netwib_uintmax*)pscanitem->ptr);
2326       break;
2327     case NETWIB_PRIV_FMT_FIELDTYPE_UINTPTR :
2328       netwib__uintptr_init_uint64(ui64, *(netwib_uintptr*)pscanitem->ptr);
2329       break;
2330     case NETWIB_PRIV_FMT_FIELDTYPE_INT32 :
2331       {
2332         netwib_int32 *p = (netwib_int32 *)pscanitem->ptr;
2333         *p = i32;
2334       }
2335       break;
2336     case NETWIB_PRIV_FMT_FIELDTYPE_INT16 :
2337       {
2338         netwib_int16 *p = (netwib_int16 *)pscanitem->ptr;
2339         if (i32 > 0 && i32 > 0xFFFF) {
2340           ret = NETWIB_ERR_PATOOHIGH;
2341         } else if (i32 < 0 && i32 < -0x8000) {
2342           ret = NETWIB_ERR_PATOOLOW;
2343         } else {
2344           *p = (netwib_int16)i32;
2345         }
2346       }
2347       break;
2348     case NETWIB_PRIV_FMT_FIELDTYPE_INT8 :
2349       {
2350         netwib_int8 *p = (netwib_int8 *)pscanitem->ptr;
2351         if (i32 > 0 && i32 > 0xFF) {
2352           ret = NETWIB_ERR_PATOOHIGH;
2353         } else if (i32 < 0 && i32 < -0x80) {
2354           ret = NETWIB_ERR_PATOOLOW;
2355         } else {
2356           *p = (netwib_int8)i32;
2357         }
2358       }
2359       break;
2360     case NETWIB_PRIV_FMT_FIELDTYPE_INT64 :
2361       {
2362         netwib_int64 *p = (netwib_int64 *)pscanitem->ptr;
2363         *p = i64;
2364       }
2365       break;
2366     case NETWIB_PRIV_FMT_FIELDTYPE_INTMAX :
2367       netwib__intmax_init_int64(i64, *(netwib_intmax*)pscanitem->ptr);
2368       break;
2369     case NETWIB_PRIV_FMT_FIELDTYPE_INTPTR :
2370       netwib__intptr_init_int64(ui64, *(netwib_intptr*)pscanitem->ptr);
2371       break;
2372     case NETWIB_PRIV_FMT_FIELDTYPE_BOOL :
2373       ret = netwib_priv_fmt_decode_bool(pbuf,
2374                                         (netwib_bool*)pscanitem->ptr);
2375       break;
2376     case NETWIB_PRIV_FMT_FIELDTYPE_CMP :
2377       ret = netwib_priv_fmt_decode_cmp(pbuf, (netwib_cmp*)pscanitem->ptr);
2378       break;
2379     case NETWIB_PRIV_FMT_FIELDTYPE_ETH :
2380       ret = netwib_eth_init_buf(pbuf, (netwib_eth*)pscanitem->ptr);
2381       break;
2382     case NETWIB_PRIV_FMT_FIELDTYPE_IP :
2383       ret = netwib_ip_init_buf(pbuf, NETWIB_IP_DECODETYPE_IP,
2384                                (netwib_ip*)pscanitem->ptr);
2385       break;
2386     case NETWIB_PRIV_FMT_FIELDTYPE_PORT :
2387       ret = netwib_port_init_buf(pbuf, (netwib_port*)pscanitem->ptr);
2388       break;
2389     case NETWIB_PRIV_FMT_FIELDTYPE_ETHS :
2390       ret = netwib_eths_add_buf((netwib_eths*)pscanitem->ptr, pbuf);
2391       break;
2392     case NETWIB_PRIV_FMT_FIELDTYPE_IPS :
2393       ret = netwib_ips_add_buf((netwib_ips*)pscanitem->ptr, pbuf);
2394       break;
2395     case NETWIB_PRIV_FMT_FIELDTYPE_PORTS :
2396       ret = netwib_ports_add_buf((netwib_ports*)pscanitem->ptr, pbuf);
2397       break;
2398     default :
2399       return(NETWIB_ERR_LOINTERNALERROR);
2400       break;
2401     }
2402   }
2403 
2404   return(ret);
2405 }
2406 
2407 /*-------------------------------------------------------------*/
netwib_priv_buf_decode_vfmt(netwib_constbuf * pbuf,netwib_conststring fmt,va_list * pap)2408 static netwib_err netwib_priv_buf_decode_vfmt(netwib_constbuf *pbuf,
2409                                               netwib_conststring fmt,
2410                                               va_list *pap)
2411 {
2412   netwib_priv_fmt_scanitem scanitem[NETWIB_REGEXP_MAXLEN];
2413   netwib_conststring pfmt;
2414   netwib_priv_fmtinfos infos;
2415   netwib_regexp arrayfound;
2416   netwib_buf regexpbuf;
2417   netwib_uint32 numitems, i;
2418   netwib_char c;
2419   netwib_err ret;
2420 
2421   netwib_er(netwib_buf_init_mallocdefault(&regexpbuf));
2422   netwib_er(netwib_buf_append_byte('^', &regexpbuf));
2423 
2424   /* analyze fmt, set regexp and array of addresses */
2425   pfmt = fmt;
2426   ret = NETWIB_ERR_OK;
2427   numitems = 0;
2428   while (NETWIB_TRUE) {
2429     c = *pfmt++;
2430     if (c == '\0') {
2431       break;
2432     } else if (c == '%') {
2433       ret = netwib_priv_fmt_analyze(pfmt, &infos);
2434       if (ret == NETWIB_ERR_OK) {
2435         pfmt += infos.skipsize;
2436         if (infos.fieldtype != NETWIB_PRIV_FMT_FIELDTYPE_PERCENT &&
2437             infos.fieldtype != NETWIB_PRIV_FMT_FIELDTYPE_END) {
2438           if (!infos.geneset || !infos.gene.skipfield) {
2439             if (numitems >= NETWIB_REGEXP_MAXLEN) {
2440               netwib_er(netwib_priv_buf_append_vfmt_error("There are too many items"));
2441               ret = NETWIB_ERR_PATOOHIGH;
2442               break;
2443             }
2444             scanitem[numitems].fmtinfos = infos;
2445             scanitem[numitems].ptr = va_arg(*pap, void*);
2446             numitems++;
2447           }
2448         }
2449         ret = netwib_priv_fmt_regexp(&regexpbuf, &infos);
2450         if (infos.fieldtype == NETWIB_PRIV_FMT_FIELDTYPE_END) {
2451           if (*pfmt != '\0') {
2452             netwib_er(netwib_priv_buf_append_vfmt_error("%$ must be the last one"));
2453             ret = NETWIB_ERR_PAFMT;
2454             break;
2455           }
2456         }
2457       }
2458     } else if (netwib_c2_isalnum(c)) {
2459       ret = netwib_buf_append_byte(c, &regexpbuf);
2460     } else if (c == ' ') {
2461       ret = netwib_buf_append_string("[ \t]+", &regexpbuf);
2462     } else {
2463       netwib_byte array[4];
2464       array[0] = '[';
2465       array[1] = c;
2466       array[2] = ']';
2467       ret = netwib_buf_append_data(array, 3, &regexpbuf);
2468     }
2469     if (ret != NETWIB_ERR_OK) {
2470       break;
2471     }
2472   }
2473   if (ret != NETWIB_ERR_OK) {
2474     netwib_er(netwib_buf_close(&regexpbuf));
2475     return(ret);
2476   }
2477 
2478   /* search regexp */
2479   ret = netwib_buf_search_regexp(pbuf, &regexpbuf, NETWIB_TRUE, &arrayfound);
2480   if (ret == NETWIB_ERR_NOTFOUND) {
2481     ret = NETWIB_ERR_NOTCONVERTED;
2482   } else if (ret == NETWIB_ERR_OK) {
2483     for (i = 0; i < numitems; i++) {
2484       ret = netwib_priv_fmt_decode(&arrayfound.array[i+1], &scanitem[i]);
2485       if (ret != NETWIB_ERR_OK) {
2486         if (ret == NETWIB_ERR_PAINT) ret = NETWIB_ERR_NOTCONVERTED;
2487         if (ret == NETWIB_ERR_PATOOHIGH) ret = NETWIB_ERR_NOTCONVERTED;
2488         if (ret == NETWIB_ERR_PATOOLOW) ret = NETWIB_ERR_NOTCONVERTED;
2489         break;
2490       }
2491     }
2492   }
2493 
2494   netwib_er(netwib_buf_close(&regexpbuf));
2495 
2496   /* leave */
2497   return(ret);
2498 }
2499 
2500 /*-------------------------------------------------------------*/
netwib_buf_decode_fmt(netwib_constbuf * pbuf,netwib_conststring fmt,...)2501 netwib_err netwib_buf_decode_fmt(netwib_constbuf *pbuf,
2502                                  netwib_conststring fmt,
2503                                  ...)
2504 {
2505   va_list ap;
2506   netwib_err ret;
2507 
2508   va_start(ap, fmt);
2509   ret = netwib_priv_buf_decode_vfmt(pbuf, fmt, &ap);
2510   va_end(ap);
2511   return(ret);
2512 }
2513