1 /*-
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * and/or other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 /* Split from vfscanf.c  */
19 
20 #define _DEFAULT_SOURCE
21 #include <_ansi.h>
22 #include <newlib.h>
23 #include <stdio.h>
24 #include "local.h"
25 
26 /*
27  * Fill in the given table from the scanset at the given format
28  * (just after `[').  Return a pointer to the character past the
29  * closing `]'.  The table has a 1 wherever characters should be
30  * considered part of the scanset.
31  */
32 
33 u_char *
__sccl(register char * tab,register u_char * fmt)34 __sccl (register char *tab,
35        register u_char *fmt)
36 {
37   register int c, n, v;
38 
39   /* first `clear' the whole table */
40   c = *fmt++;			/* first char hat => negated scanset */
41   if (c == '^')
42     {
43       v = 1;			/* default => accept */
44       c = *fmt++;		/* get new first char */
45     }
46   else
47     v = 0;			/* default => reject */
48   /* should probably use memset here */
49   for (n = 0; n < 256; n++)
50     tab[n] = v;
51   if (c == 0)
52     return fmt - 1;		/* format ended before closing ] */
53 
54   /*
55    * Now set the entries corresponding to the actual scanset to the
56    * opposite of the above.
57    *
58    * The first character may be ']' (or '-') without being special; the
59    * last character may be '-'.
60    */
61 
62   v = 1 - v;
63   for (;;)
64     {
65       tab[c] = v;		/* take character c */
66     doswitch:
67       n = *fmt++;		/* and examine the next */
68       switch (n)
69 	{
70 
71 	case 0:		/* format ended too soon */
72 	  return fmt - 1;
73 
74 	case '-':
75 	  /*
76 	   * A scanset of the form [01+-] is defined as `the digit 0, the
77 	   * digit 1, the character +, the character -', but the effect of a
78 	   * scanset such as [a-zA-Z0-9] is implementation defined.  The V7
79 	   * Unix scanf treats `a-z' as `the letters a through z', but treats
80 	   * `a-a' as `the letter a, the character -, and the letter a'.
81 	   *
82 	   * For compatibility, the `-' is not considerd to define a range if
83 	   * the character following it is either a close bracket (required by
84 	   * ANSI) or is not numerically greater than the character we just
85 	   * stored in the table (c).
86 	   */
87 	  n = *fmt;
88 	  if (n == ']' || n < c)
89 	    {
90 	      c = '-';
91 	      break;		/* resume the for(;;) */
92 	    }
93 	  fmt++;
94 	  do
95 	    {			/* fill in the range */
96 	      tab[++c] = v;
97 	    }
98 	  while (c < n);
99 #if 1			/* XXX another disgusting compatibility hack */
100 	  /*
101 	   * Alas, the V7 Unix scanf also treats formats such
102 	   * as [a-c-e] as `the letters a through e'. This too
103 	   * is permitted by the standard....
104 	   */
105 	  goto doswitch;
106 #else
107 	  c = *fmt++;
108 	  if (c == 0)
109 	    return fmt - 1;
110 	  if (c == ']')
111 	    return fmt;
112 #endif
113 
114 	  break;
115 
116 
117 	case ']':		/* end of scanset */
118 	  return fmt;
119 
120 	default:		/* just another character */
121 	  c = n;
122 	  break;
123 	}
124     }
125   /* NOTREACHED */
126 }
127