summaryrefslogtreecommitdiff
path: root/formstuff
diff options
context:
space:
mode:
Diffstat (limited to 'formstuff')
-rw-r--r--formstuff223
1 files changed, 223 insertions, 0 deletions
diff --git a/formstuff b/formstuff
new file mode 100644
index 0000000000..f0e47241c0
--- /dev/null
+++ b/formstuff
@@ -0,0 +1,223 @@
+FF *
+parse_format()
+{
+ FF froot;
+ FF *flinebeg;
+ char *eol;
+ register FF *fprev = &froot;
+ register FF *fcmd;
+ register char *s;
+ register char *t;
+ register SV *sv;
+ bool noblank;
+ bool repeater;
+
+ Zero(&froot, 1, FF);
+ s = bufptr;
+ while (s < bufend || (rsfp && (s = sv_gets(linestr,rsfp, 0)) != Nullch)) {
+ curcop->cop_line++;
+ if (in_eval && !rsfp) {
+ eol = index(s,'\n');
+ if (!eol++)
+ eol = bufend;
+ }
+ else
+ eol = bufend = linestr->sv_ptr + linestr->sv_cur;
+ if (perldb) {
+ SV *tmpstr = NEWSV(89,0);
+
+ sv_setpvn(tmpstr, s, eol-s);
+ av_store(GvAV(curcop->cop_filegv), (int)curcop->cop_line,tmpstr);
+ }
+ if (*s == '.') {
+ /*SUPPRESS 530*/
+ for (t = s+1; *t == ' ' || *t == '\t'; t++) ;
+ if (*t == '\n') {
+ bufptr = s;
+ return froot.ff_next;
+ }
+ }
+ if (*s == '#') {
+ s = eol;
+ continue;
+ }
+ flinebeg = Nullfield;
+ noblank = FALSE;
+ repeater = FALSE;
+ while (s < eol) {
+ Newz(804,fcmd,1,FF);
+ fprev->ff_next = fcmd;
+ fprev = fcmd;
+ for (t=s; t < eol && *t != '@' && *t != '^'; t++) {
+ if (*t == '~') {
+ noblank = TRUE;
+ *t = ' ';
+ if (t[1] == '~') {
+ repeater = TRUE;
+ t[1] = ' ';
+ }
+ }
+ }
+ fcmd->ff_pre = nsavestr(s, t-s);
+ fcmd->ff_presize = t-s;
+ s = t;
+ if (s >= eol) {
+ if (noblank)
+ fcmd->ff_flags |= FFf_NOBLANK;
+ if (repeater)
+ fcmd->ff_flags |= FFf_REPEAT;
+ break;
+ }
+ if (!flinebeg)
+ flinebeg = fcmd; /* start values here */
+ if (*s++ == '^')
+ fcmd->ff_flags |= FFf_CHOP; /* for doing text filling */
+ switch (*s) {
+ case '*':
+ fcmd->ff_type = FFt_LINES;
+ *s = '\0';
+ break;
+ case '<':
+ fcmd->ff_type = FFt_LEFT;
+ while (*s == '<')
+ s++;
+ break;
+ case '>':
+ fcmd->ff_type = FFt_RIGHT;
+ while (*s == '>')
+ s++;
+ break;
+ case '|':
+ fcmd->ff_type = FFt_CENTER;
+ while (*s == '|')
+ s++;
+ break;
+ case '#':
+ case '.':
+ /* Catch the special case @... and handle it as a string
+ field. */
+ if (*s == '.' && s[1] == '.') {
+ goto default_format;
+ }
+ fcmd->ff_type = FFt_DECIMAL;
+ {
+ char *p;
+
+ /* Read a run_format in the form @####.####, where either group
+ of ### may be empty, or the final .### may be missing. */
+ while (*s == '#')
+ s++;
+ if (*s == '.') {
+ s++;
+ p = s;
+ while (*s == '#')
+ s++;
+ fcmd->ff_decimals = s-p;
+ fcmd->ff_flags |= FFf_DP;
+ } else {
+ fcmd->ff_decimals = 0;
+ }
+ }
+ break;
+ default:
+ default_format:
+ fcmd->ff_type = FFt_LEFT;
+ break;
+ }
+ if (fcmd->ff_flags & FFf_CHOP && *s == '.') {
+ fcmd->ff_flags |= FFf_MORE;
+ while (*s == '.')
+ s++;
+ }
+ fcmd->ff_size = s-t;
+ }
+ if (flinebeg) {
+ again:
+ if (s >= bufend &&
+ (!rsfp || (s = sv_gets(linestr, rsfp, 0)) == Nullch) )
+ goto badform;
+ curcop->cop_line++;
+ if (in_eval && !rsfp) {
+ eol = index(s,'\n');
+ if (!eol++)
+ eol = bufend;
+ }
+ else
+ eol = bufend = linestr->sv_ptr + linestr->sv_cur;
+ if (perldb) {
+ SV *tmpstr = NEWSV(90,0);
+
+ sv_setpvn(tmpstr, s, eol-s);
+ av_store(GvAV(curcop->cop_filegv),
+ (int)curcop->cop_line,tmpstr);
+ }
+ if (strnEQ(s,".\n",2)) {
+ bufptr = s;
+ yyerror("Missing values line");
+ return froot.ff_next;
+ }
+ if (*s == '#') {
+ s = eol;
+ goto again;
+ }
+ sv = flinebeg->ff_unparsed = NEWSV(91,eol - s);
+ sv->sv_u.sv_hv = curstash;
+ sv_setpvn(sv,"(",1);
+ flinebeg->ff_line = curcop->cop_line;
+ eol[-1] = '\0';
+ if (!flinebeg->ff_next->ff_type || index(s, ',')) {
+ eol[-1] = '\n';
+ sv_catpvn(sv, s, eol - s - 1);
+ sv_catpvn(sv,",$$);",5);
+ s = eol;
+ }
+ else {
+ eol[-1] = '\n';
+ while (s < eol && isSPACE(*s))
+ s++;
+ t = s;
+ while (s < eol) {
+ switch (*s) {
+ case ' ': case '\t': case '\n': case ';':
+ sv_catpvn(sv, t, s - t);
+ sv_catpvn(sv, "," ,1);
+ while (s < eol && (isSPACE(*s) || *s == ';'))
+ s++;
+ t = s;
+ break;
+ case '$':
+ sv_catpvn(sv, t, s - t);
+ t = s;
+ s = scan_ident(s,eol,tokenbuf,FALSE);
+ sv_catpvn(sv, t, s - t);
+ t = s;
+ if (s < eol && *s && index("$'\"",*s))
+ sv_catpvn(sv, ",", 1);
+ break;
+ case '"': case '\'':
+ sv_catpvn(sv, t, s - t);
+ t = s;
+ s++;
+ while (s < eol && (*s != *t || s[-1] == '\\'))
+ s++;
+ if (s < eol)
+ s++;
+ sv_catpvn(sv, t, s - t);
+ t = s;
+ if (s < eol && *s && index("$'\"",*s))
+ sv_catpvn(sv, ",", 1);
+ break;
+ default:
+ yyerror("Please use commas to separate fields");
+ }
+ }
+ sv_catpvn(sv,"$$);",4);
+ }
+ }
+ }
+ badform:
+ bufptr = SvPV(linestr);
+ yyerror("Format not terminated");
+ return froot.ff_next;
+}
+