perl 5.0 alpha 2
[p5sagit/p5-mst-13.2.git] / formstuff
1 FF *
2 parse_format()
3 {
4     FF froot;
5     FF *flinebeg;
6     char *eol;
7     register FF *fprev = &froot;
8     register FF *fcmd;
9     register char *s;
10     register char *t;
11     register SV *sv;
12     bool noblank;
13     bool repeater;
14
15     Zero(&froot, 1, FF);
16     s = bufptr;
17     while (s < bufend || (rsfp && (s = sv_gets(linestr,rsfp, 0)) != Nullch)) {
18         curcop->cop_line++;
19         if (in_eval && !rsfp) {
20             eol = index(s,'\n');
21             if (!eol++)
22                 eol = bufend;
23         }
24         else
25             eol = bufend = linestr->sv_ptr + linestr->sv_cur;
26         if (perldb) {
27             SV *tmpstr = NEWSV(89,0);
28
29             sv_setpvn(tmpstr, s, eol-s);
30             av_store(GvAV(curcop->cop_filegv), (int)curcop->cop_line,tmpstr);
31         }
32         if (*s == '.') {
33             /*SUPPRESS 530*/
34             for (t = s+1; *t == ' ' || *t == '\t'; t++) ;
35             if (*t == '\n') {
36                 bufptr = s;
37                 return froot.ff_next;
38             }
39         }
40         if (*s == '#') {
41             s = eol;
42             continue;
43         }
44         flinebeg = Nullfield;
45         noblank = FALSE;
46         repeater = FALSE;
47         while (s < eol) {
48             Newz(804,fcmd,1,FF);
49             fprev->ff_next = fcmd;
50             fprev = fcmd;
51             for (t=s; t < eol && *t != '@' && *t != '^'; t++) {
52                 if (*t == '~') {
53                     noblank = TRUE;
54                     *t = ' ';
55                     if (t[1] == '~') {
56                         repeater = TRUE;
57                         t[1] = ' ';
58                     }
59                 }
60             }
61             fcmd->ff_pre = nsavestr(s, t-s);
62             fcmd->ff_presize = t-s;
63             s = t;
64             if (s >= eol) {
65                 if (noblank)
66                     fcmd->ff_flags |= FFf_NOBLANK;
67                 if (repeater)
68                     fcmd->ff_flags |= FFf_REPEAT;
69                 break;
70             }
71             if (!flinebeg)
72                 flinebeg = fcmd;                /* start values here */
73             if (*s++ == '^')
74                 fcmd->ff_flags |= FFf_CHOP;     /* for doing text filling */
75             switch (*s) {
76             case '*':
77                 fcmd->ff_type = FFt_LINES;
78                 *s = '\0';
79                 break;
80             case '<':
81                 fcmd->ff_type = FFt_LEFT;
82                 while (*s == '<')
83                     s++;
84                 break;
85             case '>':
86                 fcmd->ff_type = FFt_RIGHT;
87                 while (*s == '>')
88                     s++;
89                 break;
90             case '|':
91                 fcmd->ff_type = FFt_CENTER;
92                 while (*s == '|')
93                     s++;
94                 break;
95             case '#':
96             case '.':
97                 /* Catch the special case @... and handle it as a string
98                    field. */
99                 if (*s == '.' && s[1] == '.') {
100                     goto default_format;
101                 }
102                 fcmd->ff_type = FFt_DECIMAL;
103                 {
104                     char *p;
105
106                     /* Read a run_format in the form @####.####, where either group
107                        of ### may be empty, or the final .### may be missing. */
108                     while (*s == '#')
109                         s++;
110                     if (*s == '.') {
111                         s++;
112                         p = s;
113                         while (*s == '#')
114                             s++;
115                         fcmd->ff_decimals = s-p;
116                         fcmd->ff_flags |= FFf_DP;
117                     } else {
118                         fcmd->ff_decimals = 0;
119                     }
120                 }
121                 break;
122             default:
123             default_format:
124                 fcmd->ff_type = FFt_LEFT;
125                 break;
126             }
127             if (fcmd->ff_flags & FFf_CHOP && *s == '.') {
128                 fcmd->ff_flags |= FFf_MORE;
129                 while (*s == '.')
130                     s++;
131             }
132             fcmd->ff_size = s-t;
133         }
134         if (flinebeg) {
135           again:
136             if (s >= bufend &&
137               (!rsfp || (s = sv_gets(linestr, rsfp, 0)) == Nullch) )
138                 goto badform;
139             curcop->cop_line++;
140             if (in_eval && !rsfp) {
141                 eol = index(s,'\n');
142                 if (!eol++)
143                     eol = bufend;
144             }
145             else
146                 eol = bufend = linestr->sv_ptr + linestr->sv_cur;
147             if (perldb) {
148                 SV *tmpstr = NEWSV(90,0);
149
150                 sv_setpvn(tmpstr, s, eol-s);
151                 av_store(GvAV(curcop->cop_filegv),
152                     (int)curcop->cop_line,tmpstr);
153             }
154             if (strnEQ(s,".\n",2)) {
155                 bufptr = s;
156                 yyerror("Missing values line");
157                 return froot.ff_next;
158             }
159             if (*s == '#') {
160                 s = eol;
161                 goto again;
162             }
163             sv = flinebeg->ff_unparsed = NEWSV(91,eol - s);
164             sv->sv_u.sv_hv = curstash;
165             sv_setpvn(sv,"(",1);
166             flinebeg->ff_line = curcop->cop_line;
167             eol[-1] = '\0';
168             if (!flinebeg->ff_next->ff_type || index(s, ',')) {
169                 eol[-1] = '\n';
170                 sv_catpvn(sv, s, eol - s - 1);
171                 sv_catpvn(sv,",$$);",5);
172                 s = eol;
173             }
174             else {
175                 eol[-1] = '\n';
176                 while (s < eol && isSPACE(*s))
177                     s++;
178                 t = s;
179                 while (s < eol) {
180                     switch (*s) {
181                     case ' ': case '\t': case '\n': case ';':
182                         sv_catpvn(sv, t, s - t);
183                         sv_catpvn(sv, "," ,1);
184                         while (s < eol && (isSPACE(*s) || *s == ';'))
185                             s++;
186                         t = s;
187                         break;
188                     case '$':
189                         sv_catpvn(sv, t, s - t);
190                         t = s;
191                         s = scan_ident(s,eol,tokenbuf,FALSE);
192                         sv_catpvn(sv, t, s - t);
193                         t = s;
194                         if (s < eol && *s && index("$'\"",*s))
195                             sv_catpvn(sv, ",", 1);
196                         break;
197                     case '"': case '\'':
198                         sv_catpvn(sv, t, s - t);
199                         t = s;
200                         s++;
201                         while (s < eol && (*s != *t || s[-1] == '\\'))
202                             s++;
203                         if (s < eol)
204                             s++;
205                         sv_catpvn(sv, t, s - t);
206                         t = s;
207                         if (s < eol && *s && index("$'\"",*s))
208                             sv_catpvn(sv, ",", 1);
209                         break;
210                     default:
211                         yyerror("Please use commas to separate fields");
212                     }
213                 }
214                 sv_catpvn(sv,"$$);",4);
215             }
216         }
217     }
218   badform:
219     bufptr = SvPV(linestr);
220     yyerror("Format not terminated");
221     return froot.ff_next;
222 }
223