oplangtext.c

Go to the documentation of this file.
00001 
00002 /*  $Id: oplangtext.c 1260 2006-04-13 06:13:10Z sethdill $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "memory.h"
00032 #include "strings.h"
00033 #include "lang.h"
00034 #include "langinternal.h"
00035 #include "op.h"
00036 #include "opinternal.h"
00037 
00038 
00039 
00040 
00041 static short langtextlastlevel; /*globals used for visit routines*/
00042 
00043 static boolean flfirstlangtextline;
00044 
00045 static short ctlinesincontinuation;
00046 
00047 static boolean fllastwascomment;
00048 
00049 static boolean flmakeitpretty;
00050 
00051 static Handle *plastcomment;
00052 
00053 
00054 
00055 
00056 static boolean backslashdelete (Handle bs) {
00057     
00058     register long len = gethandlesize (bs);
00059     
00060     if (len > 0 && (*bs) [len - 1] == '\\') {
00061         
00062         popfromhandle (bs, 1, nil);
00063         
00064         return (true);
00065         }
00066     
00067     return (false);
00068     } /*backslashdelete*/
00069 
00070 
00071 static boolean poptrailingwhitespacehandle (Handle bs) {
00072     
00073     /*
00074     return true if there were trailing "whitespace" characters to be popped.
00075     */
00076     
00077     register long i, ct;
00078     
00079     ct = gethandlesize (bs);
00080     
00081     for (i = ct; i > 0; i--)
00082     
00083         if (!whitespacechar ((*bs) [i - 1])) { /*found a non-blank character*/
00084             
00085             sethandlesize (bs, i);
00086             
00087             return (i < ct);
00088             }
00089     
00090     sethandlesize (bs, 0);
00091     
00092     return (true); /*string is all blank*/
00093     } /*poptrailingwhitespacehandle*/
00094 
00095 static boolean remainingsubheadsarecomments (hdlheadrecord hnode) {
00096     
00097     /*
00098     are all of the remaining subheads (at the current level) comments?
00099     */
00100     
00101     hdlheadrecord nomad = hnode;
00102     
00103     if (!(**nomad).flcomment)
00104         return false;
00105     
00106     while (opnavigate (down, &nomad)) {
00107         
00108         if (!(**nomad).flcomment)
00109             return false;
00110         
00111         }
00112     
00113     return true;
00114     } /*remainingsubheadsarecomments*/
00115 
00116 
00117 static boolean oplangtextvisit (hdlheadrecord hnode, ptrvoid refcon) {
00118     
00119     /*
00120     push the text of the indicated node onto the langtext output handle.
00121     
00122     we flatten out the structure in the language understood by the parser.
00123     
00124     e.g. if we move in a level, we insert a left curly bracket.  out a level
00125     a right curly bracket.
00126     
00127     carriage returns are inserted into the text so that the parser knows
00128     which line generated the code, this makes  error reporting and 
00129     debugging possible.
00130     
00131     11/12/91 dmb: push '{' when actually entering deeper level rather than 
00132     when subheads are present, so single comment subhead is handled correctly.
00133     also, don't push a semicolon before an empty statement; otherwise, blank 
00134     lines in a locals block (and perhaps elsewhere) generate syntax errors.
00135     
00136     12/9/91 dmb: support backslash for continuation lines.  also, need to look 
00137     ahead for non-comment lines in order to place opening '{' at end of correct 
00138     line; otherwise, debugger can step onto a comment line
00139     
00140     12/13/91 dmb: added support for flmakeitpretty so that langtext can be 
00141     exported in a useful form
00142     
00143     5/6/93 dmb: test for "else" is now case-insensitive
00144     
00145     2.1b2 dmb: don't add returns until after continuation lines are complete
00146 
00147     5.0a16 dmb: don't require else to be on a line by itself
00148     
00149     6.0a13 dmb: rewrote to use handles, handlestreams
00150     
00151     2006-01-23 smd: lots of changes when flmakepretty is true,
00152     to fix problems with round trip between script outline and text.
00153     This function is in desperate need of a rewrite, but it seem to work now
00154     for every test case I could come up with.
00155     */
00156     
00157     hdlheadrecord h = hnode;
00158     handlestream *langtext = (handlestream *) refcon;
00159     short level;
00160     bigstring bs;
00161     Handle bshead;
00162     Handle bscomment = nil;
00163     boolean fltobecontinued = false;
00164     boolean flcomment;
00165     boolean flparentwascomment = false;
00166     hdlheadrecord nomad;
00167     bigstring bsfirst;
00168     byte ch;
00169     long len1, len2;
00170     boolean fl = false;
00171     
00172     level = (**h).headlevel;
00173     
00174     flcomment = opnestedincomment (h);
00175     
00176     if (flcomment) { /*just generate a blank line for a comment line*/
00177         
00178         bshead = nil;
00179         
00180         if (flmakeitpretty) {
00181             
00182             if (!copyhandle ((**h).headstring, &bscomment)) 
00183                 goto exit;
00184             
00185             ch = chcomment;
00186             
00187             if (!insertinhandle (bscomment, 0, &ch, 1L))
00188                 goto exit;
00189             }
00190         
00191         nomad = h;
00192         
00193         if (opnavigate (left, &nomad) && opnestedincomment (nomad)) {
00194             
00195             flparentwascomment = true;
00196             
00197             goto L2;
00198             }
00199         
00200         if (level > langtextlastlevel) {
00201             
00202             nomad = h;
00203             
00204             while (true) {
00205                 
00206                 if (!opnavigate (down, &nomad)) /*no more siblings*/
00207                     goto L2;
00208                 
00209                 if (!opnestedincomment (nomad))
00210                     break;
00211                 }
00212             }
00213         
00214         fltobecontinued = ctlinesincontinuation > 0; /*don't let comment interrupt continuation*/
00215         }
00216     else {
00217         
00218         if (!copyhandle ((**h).headstring, &bshead)) 
00219             goto exit;
00220         
00221         fltobecontinued = backslashdelete (bshead); /*pop off continuation marker*/
00222         }
00223     
00224     len1 = gethandlesize (bshead); /*get size with comments*/
00225     
00226     if (len1 > 0) {
00227         
00228         len2 = langcommentdelete (chcomment, (byte *) (*bshead), len1);
00229         
00230         if (len2 >= 0) { /* line is partly a comment */
00231         
00232             if (flmakeitpretty) { /*for exporting, we want to *add* comment character*/
00233                 
00234                 if (!loadhandleremains (len2, bshead, &bscomment))
00235                     goto exit;
00236                 
00237                 if ((gethandlesize (bscomment) > 0) && (len2 > 0))
00238                     insertinhandle (bscomment, 0, " ", 1L);
00239                 }
00240             
00241             sethandlesize (bshead, len2);
00242             }
00243         }
00244     
00245     if (!fltobecontinued && bshead)
00246         poptrailingwhitespacehandle (bshead); /*pop blanks, returns, tabs, etc at end of string*/
00247     
00248     if (ctlinesincontinuation == 0) { /*not continuing a previous line*/
00249         
00250         if (level > langtextlastlevel) { /*beginning of new body*/
00251             
00252             setstringwithchar ('{', bs); /*need opening brace*/
00253             
00254             if (flmakeitpretty)
00255                 insertchar (chspace, bs);
00256             }
00257         else {
00258             
00259             filledstring ('}', langtextlastlevel - level, bs); /*may need closing braces*/
00260             
00261             if ((level < langtextlastlevel) || !fllastwascomment) {
00262                 
00263                 if (bshead)
00264                     textfirstword ((ptrbyte) (*bshead), gethandlesize (bshead), chspace, bsfirst);
00265                 else
00266                     setemptystring (bsfirst);
00267 
00268                 if (!equalidentifiers (bsfirst, BIGSTRING (STR_else))) { /*never want a semicolon before else*/
00269                     
00270                     if (!flmakeitpretty || !flcomment || !remainingsubheadsarecomments (h))  /* no semicolon before the closing braces */
00271                         pushchar (';', bs);
00272                     }
00273                 }
00274             }
00275         
00276         if (!writehandlestreamstring (langtext, bs))
00277             goto exit;
00278         
00279         langtextlastlevel = level;
00280         }
00281     
00282     fllastwascomment = flcomment || isemptyhandle (bshead);
00283     
00284     L2:
00285     
00286     if (flmakeitpretty && !flcomment) {
00287         
00288         if (!writehandlestreamhandle (langtext, *plastcomment))
00289             goto exit;
00290         
00291         disposehandle (*plastcomment);
00292         
00293         *plastcomment = bscomment;
00294         
00295         }
00296     
00297     if (!flfirstlangtextline && (ctlinesincontinuation == 0)) {
00298         
00299         setstringwithchar (chreturn, bs); /*return goes before the head string*/
00300 
00301     #ifdef xxxWIN95VERSION
00302         pushchar (chlinefeed, bs);
00303     #endif
00304         
00305         if (flmakeitpretty) {
00306             
00307             while (--level >= 0)
00308                 pushchar (chtab, bs);
00309             }
00310         
00311         if (flmakeitpretty && flparentwascomment) {
00312             
00313             if (!pushtexthandle (bs, *plastcomment))
00314                 goto exit;
00315             
00316             }
00317         else if (flmakeitpretty && flcomment) {
00318             
00319             if (!inserttextinhandle (bscomment, 0L, bs))
00320                 goto exit;
00321             
00322             }
00323         else {
00324             
00325             if (!writehandlestreamstring (langtext, bs))
00326                 goto exit;
00327             
00328             }
00329         }
00330     
00331     flfirstlangtextline = false;
00332     
00333     if (flmakeitpretty && flcomment) {
00334         
00335         if (! *plastcomment)
00336             
00337             *plastcomment = bscomment;
00338             
00339         else {
00340             
00341             if (!pushhandle (bscomment, *plastcomment))
00342                 goto exit;
00343             
00344             }
00345         }
00346     else {
00347         
00348         if (!writehandlestreamhandle (langtext, bshead))
00349             goto exit;
00350         }
00351     
00352     if (fltobecontinued)
00353         ++ctlinesincontinuation;
00354     else {
00355         
00356         if (ctlinesincontinuation > 0) {
00357             
00358             if (!flmakeitpretty) {
00359                 
00360                 filledstring (chreturn, ctlinesincontinuation, bs); /*account for all input lines*/
00361                 
00362                 if (!writehandlestreamstring (langtext, bs))
00363                     goto exit;
00364                 }
00365             
00366             ctlinesincontinuation = 0;
00367             }
00368         }
00369     
00370     fl = true; //natural exit
00371     
00372   exit:
00373     disposehandle (bshead);
00374     
00375     return (fl);
00376     } /*oplangtextvisit*/
00377 
00378 
00379 boolean opgetlangtext (hdloutlinerecord houtline, boolean flpretty, Handle *htext) {
00380     
00381     /*
00382     7/29/91 dmb: use writeeditbuffer to flush typing, not unload/load
00383     
00384     2.1b8 dmb: call new langaddapplescriptsyntax for 'ascr' signature
00385     
00386     6.0a13 dmb: rewrote to use handles, handlestreams
00387     */
00388     
00389     register hdloutlinerecord ho = houtline;
00390     bigstring bs;
00391     Handle bslastcomment;
00392     OSType signature = (**ho).outlinesignature;
00393     handlestream s;
00394     
00395     #if !flruntime
00396     
00397     if ((**ho).hbuffer != nil) { /*the user is editing text, ibeam cursor mode*/
00398         
00399         oppushoutline (ho);
00400         
00401         opwriteeditbuffer (); /*force buffer into outline structure*/
00402         
00403         oppopoutline ();
00404         }
00405     
00406     #endif
00407     
00408     setemptystring (bs);
00409     
00410     *htext = nil;
00411     
00412     openhandlestream (nil, &s); //handle will be created on first write
00413     
00414     if (signature != 'LAND') {
00415         
00416         if (!opoutlinetotextstream (ho, true, &s))
00417             goto error;
00418         
00419         *htext = closehandlestream (&s);
00420         
00421         #ifdef MACVERSION
00422 
00423             if (signature == 'ascr')
00424                 langaddapplescriptsyntax (*htext);
00425             
00426         #endif
00427         
00428         return (true);
00429         }
00430     
00431 //  hlangtext = *htext; /*copy so visit routine can find it*/
00432     
00433     langtextlastlevel = 0;
00434     
00435     flfirstlangtextline = true;
00436     
00437     ctlinesincontinuation = 0;
00438     
00439     fllastwascomment = true;
00440     
00441     bslastcomment = nil;
00442     
00443     plastcomment = &bslastcomment; /*make available to visit routine*/
00444     
00445     flmakeitpretty = flpretty;
00446     
00447     if (!opsiblingvisiter ((**houtline).hsummit, false, &oplangtextvisit, &s))
00448         goto error;
00449     
00450     filledstring ('}', langtextlastlevel, bs); /*close all outstanding levels with }s*/
00451     
00452     if (!writehandlestreamstring (&s, bs))
00453         goto error;
00454     
00455     if (flmakeitpretty)
00456         if (!writehandlestreamhandle (&s, bslastcomment))
00457             goto error;
00458     
00459     disposehandle (bslastcomment);
00460     
00461     *htext = closehandlestream (&s);
00462     
00463     return (true);
00464     
00465     error: {
00466     
00467         disposehandlestream (&s);
00468         
00469         return (false);
00470         }
00471     } /*opgetlangtext*/
00472 
00473 
00474 

Generated on Wed May 31 18:19:57 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6