2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: scan.c /main/3 1995/11/08 09:42:39 rswiston $ */
25 Copyright 1986 Tandem Computers Incorporated.
26 This product and information is proprietary of Tandem Computers Incorporated.
27 Copyright 1986, 1987, 1988, 1989 Hewlett-Packard Co.
30 /* Scan.c is the scanner for program PARSER */
53 /* Actually read a character from an input stream */
54 int m_actgetc(M_NOPAR)
58 c = m_getc(m_sysent[m_sysecnt]) ;
59 m_saveline[m_svlncnt[m_sysecnt]][m_sysecnt] = c ;
60 if (++m_svlncnt[m_sysecnt] >= M_LINELENGTH) {
61 m_svlncnt[m_sysecnt] = 0 ;
62 m_svlnwrap[m_sysecnt] = TRUE ;
67 /* Expand an entity reference */
68 void m_entexpand(openent)
76 m_ungetachar(M_NULLVAL, M_EE, FALSE) ;
78 m_opene[m_eopencnt - 1] = openent ;
80 if (m_stacktop->element &&
81 m_element[m_stacktop->element - 1].content == M_RCDATA)
83 if (m_curcon == LITCON || m_curcon == LITACON)
85 if (! openent->wheredef) {
87 m_err1("%s: System error -- no definition for predeclared entity",
92 if (m_curcon == ENTINLIT)
93 if (openent->type != M_GENERAL) {
95 m_err1("%s: Typed entity not allowed in parameter value",
100 if (m_eopencnt > M_ENTLVL) {
102 m_err1("%s: Too many nested entities", openent->name) ;
106 for (i = 0 ; i < m_eopencnt - 1; i++)
107 if (m_opene[i] == openent) {
109 m_err1("Recursive call to entity %s ignored", openent->name) ;
114 /* If SDATA or PI entity (regular or CODE) at beginning of document
115 instance, call m_startdoc and reset m_curcon past preamble */
116 if (m_curcon == PREAMBLE &&
117 (openent->type == M_SDATA ||
118 openent->type == M_CODESDATA ||
119 openent->type == M_PI ||
120 openent->type == M_CODEPI)) {
127 if (openent->type == M_SDATA || openent->type == M_CODESDATA) {
128 if (! m_stacktop->intext) {
129 if (! m_strtproc(M_NULLVAL)) {
130 if (m_stacktop->oldtop)
131 m_err1("SDATA entity not allowed at this point in %s",
132 m_nameofelt(m_stacktop->element)) ;
134 m_error("Document may not start with SDATA entity") ;
137 m_stacktop->firstre = TRUE ;
138 m_stacktop->intext = TRUE ;
139 if (m_curcon == ELCON || m_curcon == DATACON)
140 m_curcon = POUNDCDATA ;
141 else if (m_curcon == NETELCON || m_curcon == NETDATACON)
142 m_curcon = NETCDATA ;
144 m_stacktop->linestat = M_DCORCET ;
149 if (openent->type == M_CODEPI || openent->type == M_CODESDATA) {
150 if (openent->type == M_CODEPI)
151 m_stacktop->linestat = M_SOMETHING ;
152 m_codeent(openent->codeindex) ;
156 /* PI or SDATA, but not CODE entity */
157 if (openent->type == M_PI || openent->type == M_SDATA) {
158 m_piaction(openent->content, openent->name, openent->type) ;
162 /* Subordinate data file */
163 if (openent->type == M_SYSTEM) {
164 m_sysent[m_sysecnt + 1] = m_openent(openent->content) ;
165 if (m_sysent[m_sysecnt + 1]) {
167 m_line[m_sysecnt] = 1 ;
168 m_svlncnt[m_sysecnt] = 0 ;
169 m_svlnwrap[m_sysecnt] = FALSE ;
171 m_trace("Opening `") ;
172 m_wctrace(openent->content) ;
174 sprintf(buffer, "%d", m_sysecnt) ;
181 m_err1("Unable to open file %s", openent->content) ;
186 /* An entity reference has been encountered. Put the content of the
187 entity, including any leading or trailing delimiters into the input
188 stream in reverse order */
189 /* Closing delimiter */
190 switch (openent->type) {
193 m_undodelim(m_dlmptr[M_TAGC - 1], FALSE) ;
197 m_undodelim(m_dlmptr[M_MDC - 1], FALSE) ;
203 /* Content of entity -- scan for end to reverse string */
204 if (openent->type == M_CDATAENT) dchar = M_CDCHAR ;
205 else dchar = M_ENTNORMAL ;
206 if (p = openent->content)
208 if (p != openent->content) {
211 m_ungetachar((int) *p, dchar, FALSE) ;
212 if (p == openent->content) break ;
216 /* Opening delimiter */
217 switch (openent->type) {
219 m_undodelim(m_dlmptr[M_STAGO - 1], FALSE) ;
223 m_undodelim(m_dlmptr[M_ETAGO - 1], FALSE) ;
227 m_undodelim(m_dlmptr[M_MDO - 1], FALSE) ;
233 } /* End m_entexpand */
235 /* An srlen-character long short-reference delimiter has been found. Verify
236 that it is not the prefix of a general delimiter recognized in context*/
237 LOGICAL m_gendelim(srlen, context)
241 int ghold[MAXD + 1] ;
244 int i, n = 0, current, delim[MAXD + 1], oldchars = 0 ;
245 int newcharstart = 0 ;
246 M_HOLDTYPE dhold[MAXD + 1], dchar ;
250 if (! (current = m_contree[context - 1])) return(FALSE) ;
252 for (i = 0 ; i <= srlen ; i++)
253 if (m_srefchartype[i] != M_RSCHAR && m_srefchartype[i] != M_WSCHAR) {
257 if (linestart) return(FALSE) ;
262 while (oldchars <= srlen &&
263 (m_srefchartype[oldchars] == M_RSCHAR ||
264 m_srefchartype[oldchars] == M_WSCHAR))
266 if (oldchars <= srlen)
267 ucase = m_hold[oldchars++] ;
269 if (! newcharstart) newcharstart = n ;
270 ghold[n] = m_getachar(&dhold[n]) ;
271 ucase = m_ctupper(ghold[n]) ;
272 if (dhold[n] != M_NORMAL && dhold[n] != M_ENTNORMAL) break ;
275 (int) m_delimtrie[i].symbol < ucase && m_delimtrie[i].more ;
277 if ((int) m_delimtrie[i].symbol == ucase) {
278 current = m_delimtrie[i].index ;
279 if (! m_delimtrie[current].symbol)
280 delim[n] = m_delimtrie[current].index ;
286 if (! newcharstart) return(FALSE) ;
287 while (n >= newcharstart - 1) {
290 /* Found a delimiter. If it ends with a letter, verify
291 that the following character is not a letter, in order
292 to issue error messages in cases such as <!ENTITYrunon ... */
293 if (m_cttype(ghold[n]) != M_NMSTART) found = TRUE ;
295 next = m_getachar(&dchar) ;
296 m_ungetachar(next, dchar, TRUE) ;
297 if (next == EOF || m_cttype(next) != M_NMSTART)
302 if (delim[n] == M_ERO || delim[n] == M_STAGO ||
303 delim[n] == M_ETAGO) {
304 next = m_getachar(&dchar) ;
305 m_ungetachar(next, dchar, TRUE) ;
306 if (! (m_cttype(next) == M_NMSTART &&
307 (dchar == M_NORMAL || dchar == M_ENTNORMAL))) {
312 while (n >= newcharstart) {
313 m_ungetachar(ghold[n], dhold[n], TRUE) ;
317 } /* End if delim[n] */
318 if (n >= newcharstart) m_ungetachar(ghold[n], dhold[n], TRUE) ;
325 /* Reads next input character from the current source file or from an
327 int m_getachar(dchar)
334 M_WCHAR wc_ee, wc_re;
339 mbtowc(&wc_ee, &mb_ee, 1);
340 mbtowc(&wc_re, &mb_re, 1);
341 if (m_toundo && m_sysecnt <= m_sourcefile[m_toundo - 1]) {
342 c = m_savechar[--m_toundo] ;
343 *dchar = m_savedchar[m_toundo] ;
344 if (*dchar == wc_ee) m_atrs = (M_WCHAR) c;
349 if (m_whitespace((M_WCHAR) c) && c != wc_re) {
350 /* White space, but not RE, i.e., space or tab */
351 for (m_wscount = 0 ; m_wscount < M_WSPACELEN ; m_wscount++) {
352 m_wspace[m_wscount] = m_actgetc() ;
353 if (! m_whitespace((M_WCHAR) m_wspace[m_wscount]) ||
354 m_wspace[m_wscount] == wc_re)
357 if (m_whitespace((M_WCHAR) m_wspace[m_wscount]) &&
358 m_wspace[m_wscount] != wc_re) {
359 m_error("Ignoring blank or tab") ;
360 while (m_whitespace((M_WCHAR) m_wspace[m_wscount]) &&
361 m_wspace[m_wscount] != wc_re)
362 m_wspace[m_wscount] = m_actgetc() ;
364 if (m_wscount > m_maxws) m_maxws = m_wscount ;
365 if (m_wspace[m_wscount] == wc_re) c = wc_re ;
367 for (i = 0 ; i <= m_wscount ; i++)
368 m_ungetachar(m_wspace[m_wscount - i], M_NORMAL, FALSE) ;
370 } /* End just read a blank or tab, is it line-trailing? */
371 } /* End read a character from file */
373 m_oldlsindex = (m_oldlsindex + 1) % M_SAVECHAR ;
374 m_oldlinestat[m_oldlsindex] = m_stacktop->linestat ;
375 m_oldatrs[m_oldlsindex] = m_atrs ;
376 if (c == wc_re && *dchar) {
377 if (*dchar == M_NORMAL) m_line[m_sysecnt]++ ;
378 m_stacktop->linestat = M_NOTHING ;
381 else if (*dchar) m_atrs = FALSE ;
385 length = wctomb(buffer, c);
389 sprintf(buffer, "%d", c) ;
392 sprintf(buffer, "%d", *dchar) ;
396 else m_trace("get(EE)\n") ;
401 /* Reads a name token */
403 void m_getname(M_WCHAR first)
405 void m_getname(first)
413 *(p = m_name) = first ;
415 c = m_getachar(&dchar) ;
416 if (c == EOF) break ;
417 if (dchar != M_NORMAL && dchar != M_ENTNORMAL) break ;
418 if (m_cttype(c) == M_NONNAME) break ;
420 if (p >= m_name + M_NAMELEN) {
422 m_error("Name too long") ;
423 while ((dchar == M_NORMAL || dchar == M_ENTNORMAL) &&
425 m_cttype(c) != M_NONNAME)
426 c = m_getachar(&dchar) ;
430 m_ungetachar(c, dchar, TRUE) ;
434 /* Reads the next token */
435 int m_gettoken(c, dchar, context)
440 int hold[MAXD + 1], next ;
442 int i, n = 0, current, delim[MAXD + 1], nexttoken ;
443 M_HOLDTYPE dhold[MAXD + 1] ;
453 if (m_stacktop->oldtop) m_shortref(context) ;
458 if (! (current = m_contree[context - 1])) {
459 *c = m_getachar(dchar) ;
464 hold[n] = m_getachar(&dhold[n]) ;
465 ucase = m_ctupper(hold[n]) ;
467 if (dhold[n] != M_NORMAL && dhold[n] != M_ENTNORMAL) break ;
469 (int) m_delimtrie[i].symbol < ucase && m_delimtrie[i].more ;
471 if ((int) m_delimtrie[i].symbol == ucase) {
472 current = m_delimtrie[i].index ;
473 if (! m_delimtrie[current].symbol)
474 delim[n] = m_delimtrie[current].index ;
483 /* Found a delimiter. If it ends with a letter, verify
484 that the following character is not a letter, in order
485 to issue error messages in cases such as <!ENTITYrunon ... */
486 if (m_cttype(hold[n]) != M_NMSTART) found = TRUE ;
488 *c = m_getachar(dchar) ;
489 m_ungetachar(*c, *dchar, TRUE) ;
490 if (*c == EOF || m_cttype(*c) != M_NMSTART) found = TRUE ;
494 if (delim[n] == M_CRO) {
495 next = m_getachar(dchar) ;
496 if ((*dchar != M_NORMAL && *dchar != M_ENTNORMAL) ||
497 (m_cttype(next) != M_DIGIT))
498 m_ungetachar(next, *dchar, TRUE) ;
500 m_scanval = next - '0' ;
502 next = m_getachar(dchar) ;
503 if ((*dchar != M_NORMAL && *dchar != M_ENTNORMAL) ||
504 (m_cttype(next) != M_DIGIT)) {
505 m_ungetachar(next, *dchar, TRUE) ;
506 if (! m_gettoken(&next, dchar, ENTREF))
507 m_ungetachar(next, *dchar, TRUE) ;
508 if (context == ELCON || context == NETELCON)
509 return(M_BLACKSPACE) ;
510 else return(M_TEXT) ;
512 m_scanval = 10 * m_scanval + next - '0' ;
513 if (m_scanval >= M_CHARSETLEN) {
514 m_error("Invalid character code") ;
515 m_scanval = (m_scanval - next + '0') / 10 ;
516 m_ungetachar(next, *dchar, TRUE) ;
517 if (context == ELCON || context == NETELCON)
518 return(M_BLACKSPACE) ;
519 else return(M_TEXT) ;
521 } /* End loop reading digits after M_CRO */
522 } /* End M_CRO followed by digit */
523 } /* End delim[n] == M_CRO */
524 else if (delim[n] == M_ERO)
526 return(m_gettoken(c, dchar,
527 (m_curcon == RCNEWENT || m_curcon == ENTINLIT) ?
528 m_curcon : context)) ;
529 /* Can be an M_ERO or M_CRO here only if not in context and hence
530 should not be treated as a delimiter */
531 if (delim[n] != M_STAGO && delim[n] != M_ETAGO &&
532 delim[n] != M_ERO && delim[n] != M_CRO)
534 /* M_STAGO and M_ETAGO recognized only if immediately followed by
535 a M_NMSTART character or by an appropriate closing delimiter
536 (latter is a short tag) */
537 if (delim[n] == M_STAGO || delim[n] == M_ETAGO) {
538 next = m_getachar(dchar) ;
539 m_ungetachar(next, *dchar, TRUE) ;
540 if (m_cttype(next) == M_NMSTART &&
541 (*dchar == M_NORMAL || *dchar == M_ENTNORMAL))
543 nexttoken = m_gettoken(&next, dchar,
544 delim[n] == M_STAGO ? SELEMENT : EELEMENT) ;
546 m_undodelim(m_dlmptr[nexttoken - 1], TRUE) ;
549 else m_ungetachar(next, *dchar, TRUE) ;
550 } /* End delim[n] is M_STAGO or M_ETAGO */
551 } /* End if (delim[n]) */
552 if (n) m_ungetachar(hold[n], dhold[n], TRUE) ;
561 /* Reads a literal */
562 void m_litproc(delim)
567 int savecon = m_curcon ;
571 char mb_re, mb_tab, mb_space, mb_null, mb_ee;
572 M_WCHAR wc_re, wc_tab, wc_space, wc_null, wc_ee;
579 mbtowc(&wc_re, &mb_re, 1);
580 mbtowc(&wc_tab, &mb_tab, 1);
581 mbtowc(&wc_space, &mb_space, 1);
582 mbtowc(&wc_null, &mb_null, 1);
583 mbtowc(&wc_ee, &mb_ee, 1);
585 m_curcon = delim == M_LIT ? LITCON : LITACON ;
586 atentlev = m_eopencnt ;
587 atdelimcon = m_curcon ;
588 for (i = 0 ; i < M_LITLEN + 1 ; i++) {
589 n = m_gettoken(&c, &dchar, m_curcon) ;
592 m_ungetachar(c, dchar, TRUE) ;
593 m_literal[i] = wc_null ;
597 m_literal[i] = (M_WCHAR) m_scanval ;
601 m_literal[i] = wc_null ;
609 m_literal[i] = wc_re ;
613 m_literal[i] = wc_space ;
617 m_literal[i] = wc_tab ;
620 m_literal[i] = (M_WCHAR) c ;
621 if (dchar == wc_ee) {
622 if (m_curcon == ENTINLIT) {
625 if (m_eopencnt == atentlev) {
626 m_curcon = atdelimcon ;
631 m_literal[i] = wc_null ;
633 m_ungetachar(wc_null, wc_ee, FALSE) ;
639 m_error("Internal error processing literal") ;
643 m_error("Literal too long") ;
644 m_literal[i] = wc_null ;
648 /* Called when a missing tagc delimiter is detected */
650 void m_missingtagc(int c, M_HOLDTYPE dchar, LOGICAL start)
652 void m_missingtagc(c, dchar, start)
659 if (start) m_mberr1("Invalid parameter or missing %s", m_tagc);
660 else m_mberr1("Missing %s in end-tag", m_tagc) ;
662 m_ungetachar(c, dchar, TRUE) ;
667 /* Have found one character in a possible short reference delimiter.
668 Prepare to look for the next one */
670 void m_nextdelimchar(int *n, int i, LOGICAL *linestart, LOGICAL newlinestart,
671 LOGICAL skipblank, unsigned char type)
673 void m_nextdelimchar(n, i, linestart, newlinestart, skipblank, type)
677 LOGICAL newlinestart ;
683 char mb_re,mb_seqchar, mb_rschar;
684 M_WCHAR wc_re,wc_seqchar, wc_rschar;
687 mbtowc(&wc_re, &mb_re, 1);
688 mb_seqchar = M_SEQCHAR;
689 mbtowc(&wc_seqchar, &mb_seqchar, 1);
690 mb_rschar = M_RSCHAR;
691 mbtowc(&wc_rschar, &mb_rschar, 1);
692 m_current[*n + 1] = m_sreftree[i].index ;
693 if (! m_sreftree[m_current[*n + 1]].symbol)
694 m_delim[*n] = m_sreftree[m_current[*n + 1]].index ;
695 *linestart = newlinestart ;
696 m_srefchartype[*n] = type ;
698 for (k = 0 ; k < M_BSEQLEN ; k++) {
699 m_hold[*n + 1 + k] = m_getachar(&m_dhold[*n + 1 + k]) ;
700 if (m_hold[*n + 1 + k] != ' ' && m_hold[*n + 1 + k] != '\t') {
701 m_ungetachar(m_hold[*n + 1 + k], m_dhold[*n + 1 + k], TRUE) ;
704 m_current[*n + 1 + k + 1] = m_current[*n + 1] ;
705 m_delim[*n + 1 + k] = m_delim[*n] ;
706 m_srefchartype[*n + 1 + k] = wc_seqchar ;
711 m_srefchartype[*n] = wc_rschar ;
714 /* Scans past a comment within a markup declaration */
715 void m_readcomments(M_NOPAR)
720 while (! m_gettoken(&c, &dchar, COMCON))
722 m_error("Document ended within a comment") ;
729 int m_scan(LOGICAL prolog)
739 char mb_ee, mb_re, mb_space, mb_tab;
740 M_WCHAR wc_ee, wc_re, wc_space, wc_tab;
743 mbtowc(&wc_ee, &mb_ee, 1);
745 mbtowc(&wc_re, &mb_re, 1);
747 mbtowc(&wc_space, &mb_space, 1);
749 mbtowc(&wc_tab, &mb_tab, 1);
752 n = m_gettoken(&c, &dchar, m_curcon) ;
755 if (n != M_ENTITYEND && m_stacktop->linestat == M_NOTHING)
756 m_stacktop->linestat = M_SOMETHING ;
765 m_ungetachar(wc_re, M_ENTNORMAL, FALSE) ;
769 m_ungetachar(wc_space, M_ENTNORMAL, FALSE) ;
773 m_ungetachar(wc_tab, M_ENTNORMAL, FALSE) ;
783 /* Check for Entity End */
787 if (m_stacktop->element &&
788 m_element[m_stacktop->element - 1].content == M_RCDATA)
790 if (m_eopencnt == m_stacktop->thisent)
792 if (m_netlevel) m_curcon = NETRCDATA ;
793 else m_curcon = RCDATAEL;
795 else if (m_eopencnt < m_stacktop->thisent)
796 m_stacktop->thisent = m_eopencnt ;
798 if (m_newcon(m_curcon - 1, M_ENTITYEND - 1)) return(M_ENTITYEND) ;
801 /* Whitespace character--check if could be data. If so,
802 if it's a RE, check if its significant */
803 if (m_whitespace((M_WCHAR) c))
805 if (! m_newcon(m_curcon - 1, M_TEXT - 1)) continue ;
806 if (c != wc_re || m_curcon == PROCINT || m_curcon == LITCON ||
807 m_curcon == LITENT || m_curcon == LITAENT)
817 if (m_sysecnt && !(prolog && (m_sysecnt == 1)))
819 m_closent(m_sysent[m_sysecnt--]) ;
822 m_trace("Closing to level ") ;
823 sprintf(buffer, "%d", m_sysecnt) ;
831 if (((m_curcon == SELEMENT ||
832 m_curcon == EELEMENT ||
833 m_curcon == ENTNAME ||
834 m_curcon == MAPNAME ||
835 m_curcon == AMAPNAME) &&
836 m_cttype(c) == M_NMSTART) ||
837 ((m_curcon == ATTNAME ||
838 m_curcon == ATTVAL ||
839 m_curcon == NEEDVI) &&
840 m_cttype(c) != M_NONNAME))
842 m_getname((M_WCHAR) c) ;
848 m_err1("Expecting value for %s",
849 &m_pname[m_parameter[m_ppsave - 1].paramname]) ;
851 m_missingtagc(c, dchar, TRUE) ;
855 m_missingtagc(c, dchar, TRUE) ;
858 m_attvonly(m_saveatt) ;
860 m_missingtagc(c, dchar, TRUE) ;
863 if (! m_stacktop->oldtop)
864 m_scanel = m_arc[m_state[0].first - 1].label ;
865 else m_scanel = m_stacktop->element ;
866 m_stacktop->holdre = FALSE ;
868 m_missingtagc(c, dchar, FALSE) ;
874 if (! m_newcon(m_curcon - 1, M_TEXT - 1)) return(M_BLACKSPACE) ;
880 /* Process explicit or implied USEMAP or ADDMAP */
882 void m_setmap(int map, LOGICAL useoradd)
884 void m_setmap(map, useoradd)
892 if (! m_stacktop->oldtop) {
893 m_error("Program error: attempt to set map for empty stack") ;
899 if (m_stacktop->map && m_stacktop->oldtop->map != m_stacktop->map)
900 m_free(m_stacktop->map, "short reference map") ;
901 /* Done, if USEMAP */
903 m_stacktop->map = NULL ;
906 /* <!ADDMAP #EMPTY> restores map from beginning of element */
907 m_stacktop->map = m_stacktop->oldtop->map ;
908 if (m_element[m_stacktop->element - 1].srefptr)
909 m_setmap(m_element[m_stacktop->element - 1].srefptr,
910 (LOGICAL) m_element[m_stacktop->element - 1].useoradd) ;
914 /* Allocate and initialize a new map if needed */
915 if (! m_stacktop->map || m_stacktop->map == m_stacktop->oldtop->map) {
917 (int *) m_malloc(sizeof(int) * M_SREFCNT, "short reference map") ;
918 for (i = 0 ; i < M_SREFCNT ; i++)
919 if (! useoradd && m_stacktop->oldtop->map)
920 m_stacktop->map[i] = m_stacktop->oldtop->map[i] ;
921 else m_stacktop->map[i] = M_NULLVAL ;
923 /* Clear an old map if replacing it */
926 for (i = 0 ; i < M_SREFCNT ; i++)
927 m_stacktop->map[i] = M_NULLVAL ;
929 /* Offset into m_map is 2, 1 for 0-based indexing, 1 for #EMPTY code */
930 for (sref = m_map[map - 2] ; sref ; sref = m_sref[sref - 1].next)
931 m_stacktop->map[m_sref[sref - 1].sref - 1] = m_sref[sref - 1].entity ;
934 /* Check for short reference delimiters */
935 void m_shortref(context)
941 LOGICAL linestart = m_atrs ;
946 mbtowc(&wc_ee, &mb_ee, 1);
948 /* If no short references defined, don't try to match one */
949 if (sizeof(m_sreftree)/sizeof(M_PTRIE) == 1) return ;
951 /* Can return if using MARKUP extensions and no map is active */
952 if (! m_conform && ! m_stacktop->map) return ;
955 m_srefchartype[0] = M_RSCHAR ;
958 /* Search through short reference delimiter tree */
964 if (linestart && m_srefchartype[n] >= M_RSCHAR)
966 for (i = m_current[n] ;
967 m_sreftree[i].more && m_sreftree[i].symbol < RS ;
969 if (m_sreftree[i].symbol == RS)
971 m_nextdelimchar(&n, i, &linestart, FALSE, FALSE, M_RSCHAR) ;
976 /* Look for white space sequence */
977 if (m_srefchartype[n] >= M_WSCHAR)
979 for (i = m_current[n] ;
980 m_sreftree[i].more && m_sreftree[i].symbol < WSSEQ ;
982 if (m_sreftree[i].symbol == WSSEQ)
984 m_nextdelimchar(&n, i, &linestart, FALSE, TRUE, M_WSCHAR) ;
989 /* Look at next character from input stream */
990 m_hold[n] = m_getachar(&m_dhold[n]) ;
991 if (m_dhold[n] == wc_ee ||
992 (m_dhold[n] != M_NORMAL && m_dhold[n] != M_ENTNORMAL))
994 m_srefchartype[n] = M_REGCHAR ;
998 /* Look for blank sequence */
999 if (m_srefchartype[n] >= M_BSCHAR &&
1000 (m_hold[n] == ' ' || m_hold[n] == '\t'))
1002 for (i = m_current[n] ;
1003 m_sreftree[i].more && m_sreftree[i].symbol < BLANKSEQ ;
1005 if (m_sreftree[i].symbol == BLANKSEQ &&
1006 (m_hold[n] == ' ' || m_hold[n] == '\t'))
1008 m_nextdelimchar(&n, i, &linestart, FALSE, TRUE, M_BSCHAR) ;
1013 /* Look for regular character */
1014 c = m_ctupper(m_hold[n]) ;
1015 if (m_cttype(c) != M_NMSTART)
1017 for (i = m_current[n] ;
1018 m_sreftree[i].more && (int) m_sreftree[i].symbol < c ;
1020 if ((int) m_sreftree[i].symbol == c)
1022 m_nextdelimchar(&n, i, &linestart, m_atrs, FALSE, M_REGCHAR) ;
1027 m_srefchartype[n] = M_REGCHAR ;
1029 } /* End search through sref delimiter tree */
1035 /* Found a delimiter. If letters were allowed in short references
1036 would check here for runon situations such as <!ENTITYrunon ... */
1037 if (m_gendelim(n, context))
1039 for (i = n ; i >= 0 ; i--)
1040 if (m_srefchartype[i] < M_WSCHAR)
1041 m_ungetachar(m_hold[i], m_dhold[i], TRUE) ;
1045 for (i = n ; i >= 0 ; i--)
1046 if (m_srefchartype[i] < M_WSCHAR)
1051 if (linestart) m_atrs = FALSE ;
1052 if (m_stacktop->map && m_stacktop->map[m_delim[n] - 1])
1055 &m_entities[m_stacktop->map[m_delim[n] - 1] - 1]) ;
1060 for (i = n ; i >= 0 ; i--)
1061 if (m_srefchartype[i] < M_WSCHAR)
1062 m_ungetachar(m_hold[i], M_CDCHAR, TRUE) ;
1066 if (m_srefchartype[n] < M_WSCHAR)
1067 m_ungetachar(m_hold[n], m_dhold[n], TRUE) ;
1068 if (m_srefchartype[n] > M_REGCHAR)
1070 m_srefchartype[n]-- ;
1079 /* Test for significant record ends. Ignore RE (\n) if
1080 1) It is the first RE in the content and no data character
1081 or contextual end tag has occurred
1082 2) Something has occurred on the line but not a data character
1083 or contextual end tag [linestat == M_SOMETHING]
1084 3) If a record end might be the last one in an element, save it
1086 void m_sigre(M_NOPAR)
1088 /* Check for first RE in content and no preceding content */
1090 (! m_stacktop->firstre && m_oldlinestat[m_oldlsindex] != M_DCORCET)) {
1091 m_stacktop->firstre = TRUE ;
1094 /* Check for line containing other than data characters or contextual
1096 if (m_start && m_oldlinestat[m_oldlsindex] == M_SOMETHING) return ;
1097 /* Save the RE to see what follows */
1099 m_stacktop->holdre = TRUE ;
1101 } /* End white space */
1103 /* Returns a context-dependent delimiter string to input stream so
1104 characters can be reread one at a time in another context */
1105 #if defined(M_PROTO)
1106 void m_undodelim(M_WCHAR *delim, LOGICAL flag)
1108 void m_undodelim(delim, flag)
1115 for (p = delim ; *p ; p++) ;
1119 m_ungetachar((int) *p, M_NORMAL, flag) ;
1120 if (p == delim) return ;
1125 /* Place a character on the current input stream. The character may have
1126 been scanned and determined not to be part of the current token or it
1127 may be in the expansion of an entity*/
1128 #if defined(M_PROTO)
1129 void m_ungetachar(int c, M_HOLDTYPE dchar, LOGICAL preread)
1131 void m_ungetachar(c, dchar, preread)
1143 mbtowc(&wc_ee, &mb_ee, 1);
1147 length = wctomb(buffer, c);
1151 sprintf(buffer, "%d", c) ;
1154 sprintf(buffer, "%d", dchar) ;
1158 else m_trace("unget(EE)\n") ;
1160 m_inctest(&m_toundo, M_SAVECHAR, "M_SAVECHAR") ;
1161 m_sourcefile[m_toundo - 1] = m_sysecnt ;
1162 m_savedchar[m_toundo - 1] = dchar ;
1163 m_savechar[m_toundo - 1] = dchar == wc_ee ? (int) m_atrs : c ;
1165 m_stacktop->linestat = m_oldlinestat[m_oldlsindex] ;
1166 m_atrs = m_oldatrs[m_oldlsindex] ;
1167 m_oldlsindex = (m_oldlsindex - 1 + M_SAVECHAR) % M_SAVECHAR ;
1169 if (m_toundo > m_maxundo) m_maxundo = m_toundo ;
1171 if (dchar == M_NORMAL) m_line[m_sysecnt]-- ;
1174 /* Have encountered an M_ERO. If the entity reference is valid, process it*/
1175 LOGICAL m_vldentref(M_NOPAR)
1184 mbtowc(&wc_ee, &mb_ee, 1);
1185 next = m_getachar(&dchar) ;
1186 if (next != EOF && m_cttype(next) == M_NMSTART && dchar != wc_ee) {
1187 m_getname((M_WCHAR) next) ;
1188 if (! m_gettoken(&next, &dchar, ENTREF))
1189 if (next != M_RE) m_ungetachar(next, dchar, TRUE) ;
1190 if (openent = (M_ENTITY *) m_lookfortrie(m_name, m_enttrie))
1191 m_entexpand(openent) ;
1192 else m_err1("Reference to undefined entity '%s'", m_name) ;
1195 m_ungetachar(next, dchar, TRUE) ;