ops.c

Go to the documentation of this file.
00001 
00002 /*  $Id: ops.c 1254 2006-04-12 20:27:14Z 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 #ifdef MACVERSION
00032     #include "mac.h"
00033 #endif
00034 
00035 #include "error.h"
00036 #include "memory.h"
00037 #include "strings.h"
00038 #include "ops.h"
00039 #include "langinternal.h"
00040 #include "shell.h"
00041 
00042 
00043 static tydirection directions [ctdirections] = {
00044     
00045     nodirection,
00046     
00047     up,
00048     
00049     down,
00050     
00051     left,
00052     
00053     right,
00054     
00055     flatup,
00056     
00057     flatdown,
00058     
00059     sorted,
00060     
00061     pageup,
00062     
00063     pagedown,
00064     
00065     pageleft,
00066     
00067     pageright
00068     };
00069 
00070 
00071 
00072 short minint (short x, short y) {
00073     
00074     return (x <= y? x : y);
00075     } /*minint*/
00076 
00077 
00078 short maxint (short x, short y) {
00079 
00080     return (x >= y? x : y);
00081     } /*maxint*/
00082 
00083 
00084 short absint (short x) {
00085 
00086     return (x >= 0? x : -x);
00087     } /*absint*/
00088 
00089 
00090 boolean delayticks (long ct) {
00091     
00092     /*
00093     6/27/91 dmb: we really want to background effectively during a delay.  
00094     we could add a high-level backgroundtask to replace the logic contained 
00095     here; let's see how long this implementation lasts first.
00096     
00097     7/27/92 dmb: set & clear scriptresting
00098     
00099     1/7/93 dmb: don't call eventavail
00100     
00101     1/18/93 dmb: langbackgroundtask now takes flresting parameter; don't set global
00102     
00103     2/19/93 dmb: take long parameter. don't ignore backgroundtask result.
00104     */
00105     
00106     register unsigned long tc;
00107     tc = gettickcount () + ct;
00108     
00109     while (gettickcount () < tc) {
00110         
00111         if (ct >= 10) { /*for non-tiny delays, allow backgrounding*/
00112             
00113             boolean fl;
00114             
00115             if (flscriptrunning)
00116                 fl = langbackgroundtask (true);
00117             else
00118                 fl = shellbackgroundtask ();
00119             
00120             if (!fl)
00121                 return (false);
00122             }
00123         } /*while*/
00124     
00125     return (true);
00126     } /*delayticks*/
00127 
00128 
00129 boolean delayseconds (long ct) {
00130     
00131     /*
00132     3/19/93 dmb: recoded to avoid overflow on large ct
00133     */
00134     
00135     register long ctloops = 1;
00136     register long ctticks = ct;
00137     
00138     if (ct > 0x00010000)
00139         ctloops = 60;
00140     else
00141         ctticks *= 60;
00142     
00143     while (--ctloops >= 0)
00144         if (!delayticks (ctticks))
00145             return (false);
00146     
00147     return (true);
00148     } /*delayseconds*/
00149 
00150 
00151 #if !flruntime
00152 
00153 void counttickloops (long *ctloops) {
00154     
00155     /*
00156     do a research project that burns up to 2 ticks real-time.
00157     
00158     sit in the tightest loop possible, watching the tick counter, and return the
00159     number of loops it took to do a tick.
00160     */
00161     
00162     register unsigned long tc;
00163     long ct = 0;
00164     
00165     tc = gettickcount ();
00166     
00167     while (gettickcount () == tc) {} /*wait for a tick "boundary"*/
00168     
00169     tc = gettickcount (); 
00170     
00171     while (gettickcount () == tc) 
00172         ct++;
00173     
00174     *ctloops = ct;
00175     } /*counttickloops*/
00176 
00177 
00178 void burntickloops (long ctloops) {
00179     
00180     /*
00181     assume the caller did a research project with counttickloops.  burn that many
00182     loops real-time.
00183     
00184     the purpose?  allows you to delay for fractions of a tick.
00185     
00186     important: our loop must have a call to gettickcount because the research loop
00187     had to do it.
00188     */
00189     
00190     register long ct = ctloops;
00191     register long i = 1;
00192     
00193     while (i <= ct) {
00194         
00195         gettickcount (); /*mimic performance of research project loop*/
00196         
00197         i++;
00198         } /*while*/
00199     } /*burntickloops*/
00200 
00201 #endif
00202 
00203 
00204 unsigned char uppercasechar (unsigned char ch) {
00205     
00206     register char c = ch;
00207     
00208     if ((c >= 'a') && (c <= 'z'))
00209         c -= 32;
00210         
00211     return (c);
00212     } /*uppercasechar*/
00213     
00214     
00215 unsigned char lowercasechar (unsigned char ch) {
00216     
00217     register char c = ch;
00218     
00219     if ((c >= 'A') && (c <= 'Z'))
00220         c += 32;
00221         
00222     return (c);
00223     } /*lowercasechar*/
00224 
00225 
00226 boolean textchar (unsigned char chcheck) {
00227     
00228     register unsigned char ch = chcheck;
00229     
00230     return (ch >= ' '  &&  ch != chdelete);
00231 
00232     /*
00233     return (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')));
00234     */
00235     } /*textchar*/
00236     
00237     
00238 void shorttostring (short shortval, bigstring bs) {
00239     
00240     numbertostring ((long) shortval, bs);
00241     } /*shorttostring*/
00242 
00243 
00244 void numbertostring (long longval, bigstring bs) {
00245     
00246 #ifdef MACVERSION
00247     NumToString (longval, bs);
00248 #endif
00249 
00250 #ifdef WIN95VERSION
00251     wsprintf (bs, "%ld", longval);
00252 
00253     #ifdef PASCALSTRINGVERSION
00254         convertcstring (bs);
00255     #endif
00256 #endif
00257     } /*numbertostring*/
00258 
00259 
00260 boolean stringtonumber (bigstring bs, long *longval) {
00261     
00262     /*
00263     fill in job needed: do error checking and return false if there are invalid
00264     characters in the string.  right now we always return true.
00265     */
00266     
00267     register short i;
00268     
00269     for (i = 1; i <= stringlength (bs); ++i) {
00270         
00271         register byte ch = bs [i];
00272         
00273         if (!isdigit (ch)) {
00274             
00275             if ((i > 1) || (ch != '+' && ch != '-')) { /*not a leading +/-*/
00276                 
00277                 setstringlength (bs, i - 1);
00278                 
00279                 break;
00280                 }
00281             }
00282         }
00283     
00284     if (isemptystring (bs)) {
00285         *longval = 0;
00286         }
00287     else {  
00288         #ifdef MACVERSION   
00289             StringToNum (bs, longval);
00290         #endif
00291         #ifdef WIN95VERSION
00292             nullterminate (bs);
00293             sscanf (stringbaseaddress(bs), "%ld", longval);
00294         #endif
00295         }
00296     
00297     return (true);
00298     } /*stringtonumber*/
00299 
00300 
00301 boolean stringtoshort (bigstring bs, short *shortval) {
00302     
00303     /*
00304     fill in job needed: do error checking and return false if there are invalid
00305     characters in the string.  right now we always return true.
00306     */
00307     
00308     long longval;
00309     
00310     stringtonumber (bs, &longval);
00311     
00312     *shortval = (short) longval;
00313     
00314     return (true);
00315     } /*stringtoshort*/
00316 
00317 
00318 #ifdef WIN95VERSION /* 3.0.4 dmb: was if __powerc */
00319 
00320     boolean stringtofloat (bigstring bs, double *pfloat) {
00321         
00322         /*
00323         3.0.2b1 dmb: C lib version for PPC
00324         */
00325         
00326         bigstring bstest;
00327         
00328         nthword (bs, 1, '.', bstest);
00329         
00330         if (!isallnumeric (bstest))
00331             return (false);
00332         
00333         nthword (bs, 2, '.', bstest);
00334         
00335         if (!isallnumeric (bstest))
00336             return (false);
00337         
00338     //  moveleft (bs + 1, bstest, stringlength (bs));
00339         
00340     //  bstest [stringlength (bs)] = chnul;
00341         
00342         /*
00343         sscanf((char *) bstest, "%lf", pfloat);
00344         */
00345         nullterminate (bs);
00346         *pfloat = atof ((char *) stringbaseaddress(bs));
00347         
00348         return (*pfloat != HUGE_VAL);
00349         } /*stringtofloat*/
00350     
00351     
00352     boolean floattostring (double num, bigstring bs) {
00353         
00354         /*
00355         3.0.2b1 dmb: C lib version for PPC
00356         */
00357         
00358         sprintf (bs, "%08.8lf", num);
00359     //  sprintf ((char *) bs, "%lf", num);
00360 
00361         convertcstring (bs);
00362         
00363         while (bs [*bs] == '0')
00364             --*bs;
00365         
00366         if (bs [*bs] == '.')
00367             pushchar ('0', bs);
00368         
00369         return (true);
00370         } /*floattostring*/
00371 
00372 #else
00373 
00374     #define Decimal decimal
00375     #define DecForm decform
00376     
00377     #ifndef THINK_C
00378     
00379     /*
00380     3.0.4 dmb: make these work with Metrowerks fp.h
00381     */
00382     
00383     static double_t str2num (byte *s) {
00384         
00385         /*
00386         3.0.4b5 dmb: must null-terminate input string
00387         */
00388         
00389         short n = 1;
00390         short p = false;
00391         decimal d;
00392         
00393         if (isemptystring (s))
00394             return 0.0;
00395         
00396         s [stringlength(s) + 1] = chnul;    /*now it's a c and p string*/
00397         
00398         str2dec ((char *) s, &n, &d, &p);
00399         
00400         return(dec2num(&d));
00401         } /*str2num*/
00402     
00403     static void num2str (decform *f, double_t x, void *s) {
00404         
00405         decimal d;
00406         
00407         num2dec (f, x, &d);
00408         dec2str (f, &d, s);
00409         
00410         convertcstring (s);
00411         } /*num2str*/
00412     
00413     #endif
00414     
00415     
00416     boolean stringtofloat (bigstring bs, double *pfloat) {
00417         
00418         /*
00419         8/7/92 dmb: use SANE routines
00420         
00421         9/22/92 dmb: added validity checking
00422         */
00423         
00424         bigstring bstest;
00425         
00426         nthword (bs, 1, '.', bstest);
00427         
00428         if (!isallnumeric (bstest))
00429             return (false);
00430         
00431         nthword (bs, 2, '.', bstest);
00432         
00433         if (!isallnumeric (bstest))
00434             return (false);
00435         
00436         *pfloat = str2num (bs);
00437         
00438         return (true);
00439         } /*stringtofloat*/
00440     
00441     
00442     boolean floattostring (double num, bigstring bs) {
00443         
00444         /*
00445         10/21/91 dmb: handle doubles bigger than the max long value.  our 
00446         technique loses some precision, but it works pretty well without 
00447         bringing in any flating point libraries.
00448         
00449         8/7/92 dmb: use SANE routines
00450         */
00451         
00452         DecForm form;
00453         
00454         form.style = FIXEDDECIMAL;
00455         
00456         form.digits = 8;
00457         
00458         num2str (&form, num, bs);
00459         
00460         while (bs [*bs] == '0')
00461             --*bs;
00462         
00463         if (bs [*bs] == '.')
00464             pushchar ('0', bs);
00465         
00466         return (true);
00467         } /*floattostring*/
00468 
00469 #endif
00470 
00471 long numberfromhandle (register Handle x) {
00472     
00473     /*
00474     return a numeric interpretation of the handle.
00475     */
00476     
00477     register long ctbytes;
00478     register long n;
00479     
00480     ctbytes = gethandlesize (x);
00481     
00482     switch (ctbytes) {
00483         
00484         case 0:
00485             n = 0;
00486         
00487             break;
00488         
00489         case 1:
00490             n = **(char **) x;
00491             
00492             break;
00493         
00494         case 2:
00495             n = **(short **) x;
00496             
00497             break;
00498         
00499         default:
00500             n = **(long **) x;
00501             
00502             break;
00503         }
00504     
00505     return (n);
00506     } /*numberfromhandle*/
00507 
00508 
00509 void exittooperatingsystem (void) {
00510     
00511     /*
00512     unconditional exit to the operating system.
00513     */
00514     
00515 #ifdef MACVERSION
00516 
00517     ExitToShell ();
00518 #endif
00519 
00520 #ifdef WIN95VERSION
00521 
00522 //  ExitProcess (0);
00523 //  PostQuitMessage (0);
00524     DestroyWindow (shellframewindow);
00525 #endif
00526     } /*exittooperatingsystem*/
00527     
00528     
00529 short dirtoindex (tydirection dir) {
00530     
00531     register short ix;
00532     
00533     for (ix = 0;  ix < ctdirections;  ++ix)
00534         if (directions [ix] == dir)
00535             return (ix);
00536     
00537     return (-1); /*not a valid direction*/
00538     } /*dirtoindex*/
00539 
00540 
00541 tydirection indextodir (short ix) {
00542     
00543     return (directions [ix]);
00544     } /*indextodir*/
00545 
00546 
00547 boolean validdirection (tydirection dir) {
00548     
00549     return (dirtoindex (dir) >= 0);
00550     } /*validdirection*/
00551 
00552 
00553 tydirection oppositdirection (tydirection dir) {
00554     
00555     /*
00556     5.0a25 dmb: pulled this out of oprepeatedbump; could be used many
00557     other places, like when scrolling
00558     */
00559 
00560     switch (dir) {
00561         
00562         case flatup:
00563             dir = flatdown;
00564             
00565             break;
00566             
00567         case flatdown:
00568             dir = flatup;
00569             
00570             break;
00571             
00572         case left:
00573             dir = right;
00574             
00575             break;
00576             
00577         case right:
00578             dir = left;
00579             
00580             break;
00581             
00582         case up:
00583             dir = down;
00584             
00585             break;
00586             
00587         case down:
00588             dir = up;
00589             
00590             break;
00591         
00592         case pageup:
00593             dir = pagedown;
00594             
00595             break;
00596         
00597         case pagedown:
00598             dir = pageup;
00599             
00600             break;
00601         
00602         case pageright:
00603             dir = pageleft;
00604             
00605             break;
00606         
00607         case pageleft:
00608             dir = pageright;
00609             
00610             break;
00611         
00612         default:
00613             dir = nodirection;
00614             
00615             break;
00616         } /*switch*/
00617     
00618     return (dir);
00619     } /*oppositdirection*/
00620         
00621 
00622 long divup (register long n, register long d) {
00623     
00624     /*
00625     divide numerator n by divisor d, rouding up
00626     */
00627     
00628     if (n >= 0)
00629         return ((n + d - 1) / d);
00630     
00631     return ((n - d + 1) / d);
00632     } /*divup*/
00633 
00634 
00635 long divround (register long n, register long d) {
00636     
00637     /*
00638     divide numerator n by divisor d, rouding as closely as possible
00639     */
00640     
00641     if (n >= 0)
00642         return ((n + d / 2) / d);
00643     
00644     return ((n - d / 2) / d);
00645     } /*divround*/
00646 
00647 
00648 long quantumize (register long n, register long q) {
00649     
00650     /*
00651     return the lowest multiple of quantum q that is greater (further from 
00652     zero) that n.  useful for quantumizing scroll distances
00653     
00654     9/25/92 dmb: check for zero; it's bogus, but data can be that way
00655     */
00656     
00657     if (q == 0)
00658         return (n);
00659     
00660     return (divup (n, q) * q);
00661     } /*quantumize*/
00662 
00663 
00664 boolean truenoop (void) {
00665     
00666     /*
00667     a noop routine for all to share.
00668     */
00669     
00670     return (true);
00671     } /*truenoop*/
00672 
00673 
00674 boolean falsenoop (void) {
00675     
00676     /*
00677     a false noop routine for all to share.
00678     */
00679     
00680     return (false);
00681     } /*falsenoop*/
00682 
00683 
00684 #define gestalttrap         0xA1AD
00685 #define unimplementedtrap   0xA09F
00686 
00687 static boolean gestaltavailable (void) {
00688 
00689     #ifdef MACVERSION
00690         #if TARGET_API_MAC_CARBON == 1
00691         //Code change by Timothy Paustian Friday, June 9, 2000 9:55:04 PM
00692         //Changed to Opaque call for Carbon
00693         //Gestalt is available for OS 9 and X
00694         return true;
00695         #else
00696 
00697         long gestaltaddr;
00698         long unimplementedaddr;
00699         
00700         gestaltaddr = (long) NGetTrapAddress (gestalttrap, ToolTrap);
00701         
00702         unimplementedaddr = (long) NGetTrapAddress (unimplementedtrap, ToolTrap);
00703         
00704         return (unimplementedaddr != gestaltaddr);  
00705         #endif
00706     #else
00707     
00708         return (false);
00709 
00710     #endif
00711     } /*gestaltavailable*/
00712 
00713 
00714 boolean gestalt (OSType selector, long *result) {
00715     
00716     #ifdef MACVERSION
00717 
00718         if (!gestaltavailable ())
00719             return (false);
00720         
00721         return (Gestalt (selector, result) == noErr);
00722 
00723     #else
00724     
00725         return (false);
00726 
00727     #endif
00728     } /*gestalt*/
00729 
00730 
00731 boolean listlink (hdllinkedlist hlinkedlist, hdllinkedlist hinsert) {
00732     
00733     /*
00734     link the item into the list
00735     
00736     2.1b5 dmb: don't set hinsert.hnext to nil if it's already in the list
00737     */
00738     
00739     register hdllinkedlist h = hlinkedlist;
00740     register hdllinkedlist hnext;
00741     
00742     if (h == nil) /*nil list*/
00743         return (false);
00744     
00745     while (true) {
00746         
00747         if (h == hinsert) /*it's already in the list*/
00748             return (true);
00749         
00750         hnext = (**h).hnext;
00751         
00752         if (hnext == nil) { /*reached last in list*/
00753             
00754             (**h).hnext = hinsert; /*push on end*/
00755             
00756             (**hinsert).hnext = nil; /*last in list*/
00757             
00758             return (true);
00759             }
00760         
00761         h = hnext; /*advance to next node*/
00762         } /*while*/
00763     } /*listlink*/
00764 
00765 
00766 boolean listunlink (hdllinkedlist hlinkedlist, hdllinkedlist hdelete) {
00767     
00768     /*
00769     unlink the indicated item from the list
00770     */
00771     
00772     register hdllinkedlist h = hlinkedlist;
00773     register hdllinkedlist hprev;
00774     register hdllinkedlist hnext;
00775     
00776     if (h == nil) /*empty list*/
00777         return (false);
00778     
00779     hprev = h;
00780     
00781     h = (**h).hnext;
00782     
00783     while (h != nil) {
00784         
00785         hnext = (**h).hnext;
00786         
00787         if (h == hdelete) { /*found it*/
00788             
00789             (**hprev).hnext = hnext;
00790             
00791             return (true);
00792             }
00793         
00794         hprev = h;
00795         
00796         h = hnext;
00797         } /*while*/
00798     
00799     return (false); /*didn't find it*/
00800     } /*listunlink*/
00801 
00802 #if __powerc || __GNUC__
00803 
00804 typedef struct {
00805     long double hi; /*maybe 8 bytes, maybe 16*/
00806     double lo;      /*ignored if hi is actually 16 bytes*/
00807     } safelongdouble;
00808 
00809 void safex80told ( const extended80 *x80, long double *x ) {
00810     
00811     /*
00812     3.0.4b3 dmb: at this point, MWC's "long doubles" are only 8 bytes. The 
00813     math library assumes that they're 16 bytes, so we need to set the "lo" 
00814     8 bytes to zero in order to avoid rounding an ununitialized data errors.
00815     
00816     thanks for John Baxter for investigating this and proposing this solution
00817     */
00818     
00819     #if 1
00820         
00821         *x = x80tod (x80);
00822         
00823     #else
00824         
00825         safelongdouble temp;
00826         
00827         x80told (x80, &temp.hi);
00828         
00829         *x = temp.hi;
00830     
00831     #endif
00832 } /*safex80told*/
00833 
00834 
00835 void safeldtox80 ( const long double *x, extended80 *x80 ) {
00836 
00837     #if 1
00838         double temp;
00839         
00840         temp = *x;
00841         
00842         dtox80 (&temp, x80);
00843     
00844     #else
00845         
00846         safelongdouble temp;
00847         
00848         temp.hi = *x;
00849         
00850         temp.lo = 0.0;
00851         
00852         ldtox80 (&temp.hi, x80);
00853     
00854     #endif
00855 } /*safeldtox80*/
00856 
00857 #endif
00858 
00859 
00860 void getsystemversionstring (bigstring bs, bigstring bsextrainfo) {
00861 
00862     #ifdef MACVERSION
00863         long x;
00864         
00865         gestalt (gestaltSystemVersion, &x);
00866         
00867         numbertostring (bcdtolong (x >> 8), bs); /* high byte is major rev., 2004-11-16 creedon - convert from bcd for correct display on Mac OS X */
00868         
00869         pushchar ('.', bs);
00870         
00871         pushint ((x & 0x00f0) >> 4, bs); /*high nibble of low byte is minor rev*/
00872         
00873         x &= 0x0f; /*lowest nibble is minor decimal rev*/
00874         
00875         if (x) {
00876             
00877             pushchar ('.', bs);
00878             
00879             pushint (x, bs);
00880             }
00881         
00882         if (bsextrainfo != nil)
00883             setemptystring (bsextrainfo);
00884         
00885     #endif
00886     
00887     #ifdef WIN95VERSION
00888         OSVERSIONINFO osinfo;
00889 
00890         osinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
00891 
00892         GetVersionEx (&osinfo);
00893 
00894         numbertostring (osinfo.dwMajorVersion, bs);
00895         
00896         pushchar ('.', bs);
00897         
00898         pushint (LOWORD(osinfo.dwMinorVersion), bs);
00899 
00900         if (LOWORD(osinfo.dwBuildNumber)) {
00901         
00902             pushchar ('.', bs);
00903             
00904             pushint (LOWORD (osinfo.dwBuildNumber), bs);
00905             }
00906         
00907         if (bsextrainfo != nil)
00908             copyctopstring (osinfo.szCSDVersion, bsextrainfo);
00909     #endif
00910     } /*getsystemversionstring*/
00911 
00912 
00913 void getsizestring (unsigned long size, bigstring bs) {
00914     
00915     unsigned long meg = 1024L * 1024L;
00916     
00917     if (size > meg) { /*greater than 1 megabyte*/
00918         
00919         unsigned long leftofdecimal, rightofdecimal;
00920         bigstring bsright;
00921         
00922         leftofdecimal = size / meg;
00923         
00924         rightofdecimal = ((size % meg) + 50) / 100;
00925         
00926         numbertostring (leftofdecimal, (byte *) bs);
00927         
00928         numbertostring (rightofdecimal, bsright);
00929         
00930         setstringlength (bsright, 1);
00931         
00932         if (bsright [1] != '0') {
00933         
00934             pushchar ('.', bs);
00935         
00936             pushstring (bsright, bs);
00937             }
00938         
00939         pushchar ('M', bs);
00940         }
00941     else {
00942         unsigned long x = size / 1024;
00943     
00944         if ((size % 1024) > 512)
00945             x++;
00946         
00947         if (x == 0)
00948             copystring (BIGSTRING ("\x05" "zero "), bs);
00949         else
00950             numbertostring (x, (byte *) bs);
00951             
00952         pushchar ('K', bs);
00953         }
00954     } /*getsizestring*/     
00955 
00956 
00957 unsigned long bcdtolong (unsigned long bcd) { /* 2004-11-23 creedon, aradke */ 
00958 
00959     /*
00960     convert a long value from BCD notation
00961     */
00962 
00963     unsigned long ret = 0;
00964     unsigned long m = 1;
00965 
00966     do {
00967         ret += m * (bcd & 0x0000000f);
00968 
00969         m *= 10;
00970 
00971         bcd >>= 4;
00972 
00973         } while (bcd != 0);
00974 
00975     return (ret);
00976     } /* bcdtolong */

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