text:
German/Grammar/Noun plurals

Noun plurals
Forming the plurals of nouns is not quite as difficult as determining their gender, but it is comparable and the process is similar. There are rules you can learn to ease the load, but there are still plenty of exceptions which must be learned by rote.

While the gender of a noun is an intrinsic property of the noun, the number, singular vs. plural, is a function of what's going on in the sentence. So while you need to know the gender of a noun to successfully decline the words around it, the nouns themselves aren't declined by gender. The factors that do affect the way a noun is declined are case and number. We shall only cover the nominative case here; fortunately, declining nouns with respect to case is comparatively straightforward and will be done when we introduce the other cases.

Possible plural endings
Again, we shall only list rules which are either widely applicable or highly consistent. (See the previous section for the meanings of these terms.) The possible plural endings are -e, -(e)r, -(e)n and -(e)s. The optional -e- in the last three endings is included when it makes the plural easy to pronounce and left out otherwise. The actual rule is complicated because it depends on the last letter of the noun, and it's not always rigorously followed anyway, so it's better to just get a feel for it by example rather than to try to memorize all the specific cases. The fifth possibility is that there is no change to the ending at all. In addition, an umlaut might be added for the plural that's not in the original noun. This mostly happens with native German words, especially those with one syllable.

The most useful rules
Here are some of the most useful rules to find which of the five plural endings to use for a given noun.

Compounds
As with with gender, compound nouns follow the Right Hand Rules law for plurals well, in other words the plural of a compound follows the same pattern as the plural of the last part. Words with specific suffixes also tend to follow the same pattern for plurals, but in this case you can often get the same result by following the other rules given here.

Vowel endings
Nouns ending with -e almost always form plurals by adding -n, regardless of gender. This is a widely applicable and consistent rule.

Nouns ending with vowels other than -e, but including -y, almost always form plurals by adding -s. Most of them are imported from other languages and, as you might expect, those would form plurals with -s anyway, especially if the source language is English or French, but there are also words that are not imported in this category as well. For example: Exceptions:
 * Oma, Opa ("grandma", "grandpa") – Omas, Opas ("grandmas", "grandpas")
 * Firma ("firm, company") – Firmen ("firms")
 * Thema ("topic, theme") – Themen ("topics")
 * Ei ("egg") – Eier ("eggs")

Penultimate 'e'
Nouns ending in -en or -er, which account for most of the nouns whose next-to-last letter is 'e', usually form their plurals without an ending at all. One way to view this is that -en and -er are already plural endings, so it would be awkward to add another plural ending to them. Nouns ending in -el often follow this pattern as well, but there are so many exceptions to this that it shouldn't be relied on. Examples: Exceptions:
 * Kuchen ("cake") – Kuchen ("cakes")
 * Zimmer ("room") – Zimmer ("rooms")
 * Fehler ("error") – Fehler ("errors")
 * Words with the -chen diminutive suffix:
 * Mädchen ("girl") – Mädchen ("girls")
 * Nouns formed from verbs:
 * Essen ("food") – Essen ("foods") – from essen ("to eat")
 * Words with the -er suffix denoting function, job, or origin:
 * Fahrer ("driver") – Fahrer ("drivers")
 * Relatives; these usually have an umlaut in the plural:
 * Bruder ("brother") – Brüder ("brothers")
 * Schwester ("sister") – Schwestern ("sisters")
 * Nummer ("number") – Nummern ("numbers")

Foreign nouns
Imported words tend to declined as in the language of origin, so, as mentioned above, nouns borrowed from French and/or English usually use the -(e)s ending in plurals. In addition to the examples already listed, there are:
 * E-Mail ("e-mail") – E-Mails ("e-mails")
 * Hotel ("Hotel") – Hotels ("Hotels")
 * Restaurant ("Restaurant") – Restaurants ("Restaurants")

Masculine nouns
When none of the above rules are applicable then you can usually find the plural using gender alone. These rules tend to have many exceptions though. Masculine nouns tend to use the -e ending to form plurals. For example:
 * Tisch ("table") – Tische ("tables")
 * Schuh ("shoe") – Schuhe ("shoes")
 * Hund ("dog") – Hunde ("dogs")

There is, however, a subset of masculine nouns that use the -(e)n ending. These are troublesome since, as we'll be covering later, they make declining nouns with respect to case much more difficult. These include: Many, but not all, of these nouns end with -e, so these follow the -e ending rule mentioned earlier.
 * Junge ("boy") – Jungen ("boys")
 * Name ("name") – Namen ("names")

There are, of course, masculine nouns that don't seem to fit into any pattern:
 * Mund ("mouth") – Münder ("mouths")

Feminine nouns
Feminine nouns almost always use the -(e)n to from plurals: Many of these nouns end with -e so this is consistent with the -e ending rule given above.
 * Ecke ("corner") – Ecken ("corners")
 * Kartoffel ("potato") – Kartoffeln ("potatoes")
 * Katze ("cat") – Katzen ("cats")

Although the rule for feminine plurals is relatively consistent, there are always a few oddballs:
 * Hand ("hand") – Hände ("hands")
 * Stadt ("city") – Städte ("cities")

Neuter nouns
Common wisdom says that neuter nouns tend to use the -(e)r ending. There are, however, nearly as many that use the -e ending, so unless you are allowed two guesses this rule is not as useful as you might hope. Examples with -(e)r:
 * Ei ("egg") – Eier ("eggs")
 * Kind ("child") – Kinder ("children")
 * Lied ("song") – Lieder ("songs")

Examples with -e:
 * Brot ("loaf of bread") – Brote ("loaves of bread")
 * Haar ("a single hair") – Haare ("hairs", including the hair on someone's head)

A neuter noun that does not follow either pattern is: It does end with an -e though, so the corresponding rule applies in this case.
 * Auge ("eye") – Augen ("eyes")

Umlauts
As seen in some of the examples above, some nouns add an umlaut to their plurals as well as, or instead of, changing their ending. As mentioned above, this happens most frequently with single syllable words and sometimes with two syllable words, generally those that have been in the language for a long time. Some examples not already mentioned:
 * Fuß ("foot") – Füße ("feet")
 * Dorf ("village") – Dörfer ("villages")
 * Garten ("garden") – Gärten ("gardens")

Singular only and plural only nouns
As in English, German has some nouns that either have no plural at all, or if they do then they are only used in certain circumstances. Similarly German has its share of nouns with no singular form. (Grammarians call these, if you want to really delve into the jargon, singularia tantum and pluralia tantum.) The situation in German is a bit more subtle than it is for English, and we'll have more to say on this when we introduce articles in the next section. Singular only nouns are usually:
 * Substances, for example:
 * Wasser – ("water")
 * These generally can form plurals if you're talking about different types and certain other cases.
 * Abstract concepts, for example:
 * Hunger – ("hunger")
 * Something that only exists as a single entity:
 * Internet – ("internet")

Plural only nouns are more difficult to classify. Examples are Note that the English versions of these words do have singular forms (though "person" as the singular of "people" is arguable), but English has its own examples such as "pants" and "scissors" for which the German equivalents are singular, Hose and Schere.
 * Eltern – ("parents")
 * Leute – ("people")

Summary
These rules allow you to find the plurals of nouns more often and more reliably than the rules for finding their gender given in the previous section. This is an unfair comparison though since many of them assume that you already know the gender of the noun in question; without knowing the gender these rules would be similarly incomplete and unreliable. Fortunately, once you have the gender and plural of a noun, you can easily fill in its entire declension table in the vast majority of cases. We're leaving out here a small but significant class of nouns derived from adjectives, and they decline more like their adjective parents than actual nouns. We'll say more about them later but we'll need to do adjectives first.

title: German/Grammar/Noun plurals


text:
Mirad Thesaurus/Nature

=Nature=

Nature (Mol)

 * mol=nature
 * mola=natural
 * molay=naturally
 * omola=unnatural, artificial
 * omolay=unnaturally, artificially
 * molay=naturally
 * molxer=to naturalize
 * molxen=naturalization
 * molxwa=naturalized
 * yizmola=supernatural, preternatural
 * yizmolat=supernatural creature
 * mol tyoyap=nature walk
 * mol meup=nature trail
 * mol tix=nature study
 * mol nelwem=nature reserve
 * mol yagbexen=nature conservancy

Soil (Mel)

 * mel=soil, ground, dirt, land
 * melika=soily, dirty
 * melaper=skim across the surface of the land
 * melber=to compost, put down soil
 * melben=composting, putting down soil
 * melbut=composter
 * melbul=compost
 * melfuf=soil pipe
 * melfyiul=fertilizer
 * melfyiulber=to fertilize
 * melfyiulben=fertilization
 * melfyiulbwa=fertilized
 * meglal=clod of earth
 * melikun=landfill
 * melilp=soil creep
 * melk=acre
 * melkag=hectare
 * melkan=acreage
 * melkip=landslide
 * melmas=parapet, rampart, earthwork
 * melned=plain, meadow, flat
 * melpaslun=earthquake
 * melpasluna=seismic
 * melpaslun-ovarea=earthquake-resistant
 * melpasluntun=seismology
 * melpasluntuna=seismological
 * melpasluntut=seismologist
 * melpier=take off
 * melpien=take-off
 * melpien pontem=departure lounge
 * melpien ujtom=departures terminal
 * melpuer=land
 * melpuen=landing
 * melpuen ujtom=arrivals terminal
 * melsiram=hanger, shed, barn
 * meltun=geography
 * meltuna=geographic
 * meltut=geographer
 * meluk=hole, ditch, grave, hole in the ground, pit, dugout
 * melukar=hoe, spade
 * melukarer=to hoe, to space
 * melukaren=hoeing, spading, ditch-digging
 * melukarut=hoer, spader, ditch digger
 * melukarwa=hoed, spaded, dug
 * gyomeluka=spade
 * gyomelukarer=to spade
 * gyomelukaren=spading
 * gyomelukarwa=spaded
 * komeluk=crypt
 * melukber=to bury, inter, entomb
 * melukben=burial, interment
 * melukbwa=buried, interred
 * glatoda melukbam=mausoleum
 * melkukmayb=burial moound, tomb
 * melukmeg=headstone, tombstone
 * meluknad=furrow, ditch, groove, trench
 * meluknyem=coffin, casket
 * melukober=to exhume
 * melukoben=exhumation
 * melukobwa=exhumed
 * melukxel=burial ceremony, burial rite
 * melukxer=to dig
 * melukxen=digging
 * melukxwa=dug
 * fyameluk=sepulcher
 * fyameluka=sepulchral
 * melvabijbul=fertilizer
 * melvyun=soilure
 * melyag=petuntse, feldspare
 * melyanbea vob=soil binder
 * melyaz=dirt pile, soil mound, mound of dirt
 * melyex=farming, agriculture
 * melyexam=farmhouse
 * melyexem=farm, plantation
 * melyexdoum=manor, hacienda, farmstead
 * melyex belar=tumbrel
 * melyexer=to farm, to work the land
 * melyexen=farming
 * melyexwa=farmed
 * melyexut=farmer
 * omelyexwa=uncultivated
 * melyex belar=
 * melyexar=hand plow
 * melyexir=plow, tiller
 * melyexiram=shed
 * melyexirer=to till, plow
 * melyexiren=tilling, plowing
 * melyexirwa=tilled, plowed
 * melyig=silica
 * melyij=hole, pit, dugout
 * melyijar=shovel, hoe
 * melyijarer=to shovel, hoe
 * melyijaren=shoveling, hoeing
 * melyijarwa=shoveled, hoed
 * melyijur=steam shovel
 * melyijber=to dig
 * melyijben=digging
 * melyijbwa=dug
 * melyijbwas=dugout
 * melyoz=hole, pit, dugout, trench, grave
 * yobmelyoz=cavern
 * yobmelyozyena=cavernous
 * melyug=flint
 * melyup=landing approach
 * melyuxrin=feudalism
 * melyuxrina=feudal, feudalistic
 * melyuxruer=to enserf
 * melyuxrueb=feudal lord, vassal
 * melyuxruen=enserfage
 * melyuxruwa=enserfed
 * melyuxrut=serf, helot, villein, peasant
 * melyuxrutan=serfdom, helotage, peasantry
 * melza=brown, olive drab
 * melzat=brown-skinned person
 * melzaxer=to brown, toast
 * melzaxwa=browned, toasted
 * melzyeg=crater, ditch, hole, cavity
 * melzyegar=pick
 * melzyegarwa=pitted
 * melzyeger=excavate
 * melzyegen=excavation
 * melzyegwa=excavated
 * melzyegur=excavator
 * magmeba melzeg=volcanic crater
 * muara melzeg=lunar crater, moon crater
 * melzyun=clod, clump of dirt
 * melzyuv=stake
 * melzyuvyan=palisade, stockade
 * tabmeluk=grave
 * tabmeluk kobiut=grave robber
 * tabmelukxer=to bury, entomb
 * tabmelukxwa=entombed, buried, interred
 * tabmelzyeg=grave
 * meltun=geography
 * meltuna=geographical
 * meltut=geographer
 * ummel=dry land
 * immel=loam
 * vobmel=glebe
 * yabmelned=plateau
 * yagmeluk=furrow, trench, ditch
 * yagmeluk dropeken=trench warfare
 * yagmelukxer=dig ditches
 * yagmelukxen=ditch-digging
 * yagmelukxut=ditch-digger
 * yanmel=continent
 * yanmela=continental
 * obyanmel=sub-continent
 * obyanmela=sub-continental
 * zeyyanmela=transcontinental
 * ebyanmela=intercontinental
 * eynyonmel=peninsula
 * eynyonmela=peninsular
 * yonmel=island
 * yonmela=insular
 * yonmelat=islander
 * yonmelog=islet
 * yonmeyl=isle
 * yonmelyan=archipelago
 * yonmelzyeg=dust well
 * zaomelfuf=soil stack
 * zyemelmep=tunnel
 * gimel=mountain
 * gimelog=hill, knob
 * gimelaya=mountainous
 * gimelut=mountaineer
 * gimel abnod=mountaintop
 * gimekim=mountain slope
 * gimelkum=mountainside
 * gimelnab=mountain chain
 * gimelsyob=foot of the mountain, mountain base
 * gimelyaprer=climb a mountain
 * gimelyapren=mountain-climbing
 * gimelyaprut=mountain-climber
 * yommel=glacier
 * yommela=glacial
 * oybmel=underground
 * oybmela=subterranean
 * aybmel=above ground
 * aybmela=above-ground
 * dopa melmas=earthwork
 * abmeltim=terrace
 * goun bi mel=patch of land
 * mel mep=dirt road
 * meel=terrain
 * mef=brick
 * meyf=slab
 * mev=porcelain
 * meav=ceramic
 * meev=pottery, earthenware
 * mek=dust, powder, grit
 * mekar=duster
 * mekarer=to dust
 * mekaya=dusty
 * mekber=to powder
 * mekes=grain, speck of dust
 * mekesa=granular
 * mekika=dust-filled
 * mekil=mash, meal, gruel
 * mekilxer=mash, crush, mill, grind
 * mekilxar=mill
 * mekilxarut=miller
 * yuvob mekil=oatmeal
 * gevob mekil=cornmeal
 * mekxer=to grind
 * mekxar=grinder, grater
 * taolmekxar=meat grinder
 * bilyig mekxar=cheese grater
 * efeyl mekxar=coffee grinder
 * mekmap=dust devil
 * mekobar=dust mop
 * mekobarer=to mop
 * mekobir=vacuum cleaner
 * mekobirer=to vacuum
 * mekovof=dust ruffle
 * mekuzlem=dust bowl
 * mekzyun=dust ball, dust kitty
 * tolmek=spice
 * tolmekaya=spicy, hot
 * tolmekber=to season
 * tolmekbwa=seasoned
 * tolmekyom=sherbet
 * drefmek=paper pulp
 * faomek=wood pulp
 * faomekar=pulper
 * faomekarer=to pulp
 * filmek=yeast
 * filmekxer=leaven
 * filmekxwa=leavened, fermented
 * ofilmekxwa=unleavened
 * ilmekuer=spray, dust
 * ilmekuar=spray gun, duster
 * marmek=star dust
 * megmek=rock dust
 * mekapaxler=sweep away dust
 * mekapaxlar=dust sweeper
 * mekkof=dust cover
 * mekmapaz=haboob
 * meknov=dust cloth
 * meknyem=dust bin
 * mekmapil=dust storm
 * miek=sand
 * miekaya=sandy
 * miekmeb=dune, sand dune
 * mag=fire
 * mog=ash
 * mav=flame
 * mov=smoke
 * mep=road
 * mepyan=network
 * meyp=route
 * meep=path
 * kumep=sidewalk
 * meip=lane
 * meup=trail
 * domep=street
 * domeap=boulevard
 * domeep=avenue
 * domeip=lane
 * ebdomep=alley
 * zeymep=bridge
 * aagmep=main road
 * agmep=highway
 * ebdoeba agmep=interstate highway
 * ebdoma agmep=interurban highway
 * aybmep=overpass
 * oybmep=underpass
 * yijmep=opportunity
 * denmep=parkway
 * dinmep=plot
 * ebmep=aisle
 * elyamep=railway
 * golmep=groove, channel
 * gasinmep=intersection
 * gumep=dogleg
 * igdomep=expressway
 * igmep=turnpike
 * kimep=ramp
 * kudomep=side street
 * kutyoyamep=sidewalk
 * musmep=stairway
 * olizmep=detour
 * oyebmep=way out, egress, exit
 * popmep=itinerary
 * tinmep=discipline
 * tyenmep=career
 * tyomep=sidewalk
 * uzmep=byway
 * vyamep=vector
 * yebmep=entryway
 * yexmep=profession
 * yuzdomep=beltway
 * yuzmep=circuit
 * yogmep=shortcut
 * zyanmep=span, bridge
 * zeymep=bridge, cross-over
 * zyadomep=broadway
 * zeypuxmep=trajectory
 * zetifmep=beltway
 * zemep=median
 * yuxnux zeymep=toll bridge
 * byoyx zeymep=suspension bridge
 * zebkyin mep=bascule bridge
 * zaobas zeymep=swing bridge
 * ha vyosa mep=the wrong way
 * ha vyasa mep=the right way
 * omep=impasse
 * loxer omep=to break an impasse
 * odoma mep=country road
 * nega mep=grade crossing
 * vyifxer mep=to clear a path
 * megyelber mep=to pave a road
 * uzabmasmep=arcade
 * mesmep=threshold
 * mamp mep=flight path
 * homep?=which way?
 * igpir mep=escape route:::
 * mem=land, country
 * memut=peasant
 * memutyan=peasantry
 * zyimem=plain
 * ilik zyimem=flood plain
 * mimol zyimem=salt flat
 * zyomem=valley, dale
 * ukmem=desert
 * eynukmem=steppe
 * ebmem=isthmus
 * memsin=scenery
 * zomem=back country, hinterland
 * tajmem=homeland, native country
 * tammem=estate
 * ummem=desert, dry land
 * vabmem=prairie, grassland
 * vobmem=brush
 * yabmem=highland, uplands
 * yijmem=field, meadow, lea, open land
 * immem=wetland, marsh
 * mimol zyimem=salt marsh
 * zyoebmem=isthmus
 * zemem=heartland
 * meabmem=hill country
 * fabmem=woodland
 * uzmem=bay, gulf
 * yebmem=inland
 * yibmem=foreign land, abroad
 * yobmem=lowland
 * meilmem=mud flat
 * mebmem=mountainous terrain
 * meb=mountain
 * magmeb=volcano
 * magmeba=volcanic
 * magmeba mog=volcanic ash
 * magujbwa magmeb=extinct volcano
 * mebabnod=mountaintop, peak, summit
 * zyimeb=plateau
 * meyb=mount
 * meab=hill
 * meeb=hillock
 * meib=mound, swell, hump, bump, tumor
 * meibog=pimple
 * meub=ridge, fold, rimple
 * meubob=rim
 * ovmilmeub=dike, bank
 * mob=precipice, chasm
 * moab=gulf, gulch
 * moeb=ravine
 * moib=cave, cavern
 * moub=ditch, furrow, trench, gutter, troove, crevasse
 * ovmoub=dyke, levee, embankment
 * moyob=cleft, crevice, cranny, fissure, gap
 * moyab=hole, hollow, pit, shaft
 * moyeb=dimple, depression, dip:
 * mub=promontory
 * mimub=cape

Water (Mil)

 * mil=water
 * mil-=hydro-, aqui-
 * mila=aquatic
 * mial=vapor, steam
 * mialxer=to vaporize
 * mialur=steam engine
 * mialvyixer=to steam-clean
 * mialika=steamy
 * miil=dew
 * alamil=soda water
 * alzyunogea mil=sparkling water
 * alzyunuka mil=still water
 * ammilbar=convector
 * ammilben=convection
 * ammilbuker=scald
 * ammilbuken=scalding
 * ammilbukwa=scalded
 * ammilzyeb=hot water bottle
 * bamil=fountain
 * bamilen=spraying
 * bamiler=to spray
 * bamilwa=sprayed
 * buixer mil=pump water
 * byimil=spring water
 * milzyaber=spray
 * milzyabar=hose, sprayer
 * milzyaben=spraying, hosing
 * milzyabwa=sprayed, hosed
 * eymilper=wade
 * eymilpen=wading
 * eymilpen miyom=wading pool
 * eymilput=wader
 * ilper=to flow, run, stream
 * ilpea mil=running water
 * ilp=flow, flux
 * zoyilp=reflux
 * yebilp=influx
 * oyebilp=outflow
 * iloker=to leak
 * ilok=leak
 * ilokyea=leaky
 * ilokyofwa=leak-proof
 * ilzyebwa mil=bottled water
 * jebmamil=monsoon
 * jomilyaoz=wake
 * mag mildiym=fire hydrant
 * mag milbuixpur=fire engine
 * malzyuynika mil=carbonated water
 * milbelar=bucket, pail, water pail
 * fyamil=holy water
 * fyamilber=baptize
 * fyamilben=baptism
 * fyamilbwa=baptized
 * gramilber=flood
 * gramilbwa=flooded
 * gramil=flood
 * mamil=rain
 * mamiler=to rain
 * mamilen=raining
 * mamilaya=rainy
 * gyimamil=downpour
 * gyimamiler=to downpour
 * gyumamil=drizzle
 * gyumamiler=to drizzle
 * mamil abof=rain canopy, rain tarp
 * mamil dazun=rain dance
 * mamil fabyan=rain forest
 * mamil igpyos=rain shower
 * mamil jeb=rainy season
 * mamil nagar=rain gauge, pluviometer
 * mamil zyunes=raindrop
 * mamilag=rainstorm
 * mamilaz=hard rain
 * mamilfuf=rain spout, gutter
 * mamilmaf=rain cloud
 * mamilovar=umbrella
 * mamiloya=rain-free
 * mamiloz=sprinkle
 * mamilozer=to sprinkle
 * mamilozen=sprinkling
 * mamilpyos=precipitation, rainfall
 * mamiltaf=raincoat
 * mamiltif=rain jacket
 * mamiltof=rain gear
 * mamilug=drizzle
 * mamiluger=to drizzle
 * mamilugyea=drizzly
 * mamiluz=rainbow
 * mil bay yom=ice water
 * mil bi ilyujar=tap water
 * mil buixar=water pump
 * mil faosyeb=tub
 * mil fyebag=water tank, water cistern
 * mil zyutom=water tower
 * mila suzyanam=aquatic museum
 * milabam=shower house
 * milabim=shower room
 * milabum=shower stall
 * milabier=to take a shower
 * milabuer=to douse
 * milama=hydrothermal
 * milamsom=water heater
 * milamxar=water heater
 * milapuxer=splash water on
 * milapyoxer=drench, douse
 * milatub=hydrofoil
 * milaya=watery
 * milaybaer=flood
 * milayper=to float
 * milaypar=flotation device
 * milaypun=flotsam
 * milbal=water pressure
 * milbar=hose, spray
 * milbektun=hydropathy
 * milbektuna=hydropathic
 * milbektut=hydropath
 * milbyek=hydrotherapy
 * milbyektun=hydrotherapeutics
 * milbyekam=wellness spa
 * milfob=hydrophyte
 * milfobyex=hydroponics
 * milfuf=water pipe
 * milfufa=hydraulic
 * milfufut=plumber
 * milmaka=hydroelectric
 * milfufyextun=hydraulic engineering
 * milfyeb=canteen
 * milfyebag=tank
 * milgoynzyabar=sprinkler
 * milifa=hyrophilic
 * milufan=hydrophobia
 * milij=spring
 * milim=water closet, bathroom, WC
 * milizbar=aqueduct
 * milkexar=douser
 * milkexer=dowse
 * milkiper=water ski
 * milkipar=water ski
 * milkyuper=float on water
 * milkyupar=float, buoy
 * milmas=levee
 * milmays=small dam, weir
 * milmemtum=hydrogeology
 * milmep=waterway, course, aqueduct
 * milmir=hydrosphere
 * milmob=waterfall, cascade, falls
 * milmoub=moat
 * milmoyeb=water well
 * milnagar=hydrometer, hydrostat
 * milnagdref=hydrograph
 * milnagaren=hydrostatics
 * milneg=body of water
 * milneyeb=reservoir
 * milnov=towel
 * milnov grun=towel hook
 * milnov somos=towel rack
 * milnoyv=hand towel
 * milnyeb=bucket
 * milnyem=aqaurium, fish tank
 * milov=tea towel
 * milovog=hand towel
 * milovarea=water-resistant
 * milovmas=dam
 * milovmasber=to dam
 * milovmasbwa=dammed
 * miloyber=to submerge, dunk
 * miloybixer=to drag underwater, drown
 * miloybixwer=to drown
 * miloybler=to sink
 * miloyper=to snorkle
 * miloypuxer=to drown, throw overboard
 * milpastun=hydrokinetics
 * milpoysler=to dip, bathe, immerse oneself
 * milpoyxler=immerse
 * milpusler=to dive
 * milpyoser=to shower, downpour
 * milpyoxer=to douse
 * milpyoxler=to plunge
 * milsirtyen=hydromechanics
 * milsom=sink
 * milsum=water bed
 * milsyeb=cistern, tub
 * miltim taf=bath robe
 * miltim=bathroom, washroom
 * miltun=hydrology
 * miltut=hydrologist
 * miltyez=hydromancy
 * miluer=irrigate, water
 * miluar=irrigator
 * miluer ha vobi=to water the plants
 * milufim=restroom
 * milufsom=toilet
 * ukxer ha milufsom=to flush the toilet
 * milvoz=water color
 * milyaoz=wave
 * milyaz=surge, surf
 * milyaz faof=surf board
 * milyazper=to surf
 * milyazput=surfer
 * milyazen=surfing
 * milyazer=to swell
 * milyazog=ripple
 * milyazoger=to ripple
 * milyeb=bowl
 * milyeber=to put into water, dip, immerse, bathe
 * milyebam=bath house
 * milyebem=bath
 * milyebim=bathroom
 * milyebsom=bathtub
 * milyebler=to drench, soak
 * milyebuxer=to dunk, throw into water
 * milyem=basin
 * milyeper=bathe
 * milyepuser=dive
 * milyepusut=diver
 * milyepus faof=diving board
 * milyex=aquiculture
 * milyongonsen=hydrolysis
 * miloybler=drown
 * miloyblawat=drowning victim
 * milyuijar=water faucet
 * milyuzper=to wallow
 * milzyaber=to shower, douse
 * milzyeber=permeate, leak
 * milzyebyofwa=impermeable, leak-proof
 * milzyeg=well
 * milzyegem=oasis
 * milzyeper=to swim
 * milzyeput=swimmer
 * milzyepam=natatorium
 * milzyepem=swimming hole
 * milzyepyem=swimming pool
 * milzyubar=water mill
 * milzyubut=miller
 * milzyun=drop of water
 * milzyuner=drip
 * milzyunea=dripping
 * milzyunog=droplet
 * milzyunyea=drippy
 * oybmila=underwater
 * omaegwa mil=uncarbonated water
 * omiluer=to dehydrate
 * yoymil=dew
 * yoymilnod=dew point
 * meil=mud
 * -il - a stub suffix for liquid things ( < mil)

Matter (Mul)

 * mul=matter, material, stuff, substance
 * mula=material
 * omula=immaterial
 * aamul=element
 * aamula=elemental
 * aamuldraf=chart of the elements
 * eymul=mixture, melange, blend, mix
 * eymulxer=mix
 * eymulxwa=mixed
 * vamul=proton
 * vemul=neutron
 * vomul=electron
 * vomula=electronic
 * zemul=nucleus, kernel, pith, pit, core, yolk
 * zemula=nuclear
 * umul=quark
 * gemul=isotope
 * gwomul=atom
 * gwomula=atomic
 * gwomula kyin=atomic weight
 * bokmul=germ, contaminant, bacterium
 * bokmulxer=infect
 * bokmulxen=infection
 * bokmulxwa=infected
 * fyumul=waste matter
 * mona mul=dark matter
 * moza mul=black matter
 * ovmul=antimatter
 * yanmul=cluster, mix, fusion, chemical
 * yanmultun=chemistry
 * yanmultuna=chemical
 * yamultut=chemist
 * volyanmul=salad
 * tejefmul=protein
 * yanbixmul=tannin
 * tummul=cytoplasm
 * yigabmul=enamel
 * pyosmul=fallout
 * zomul=end matter
 * omul=non-entity
 * -ul = stub suffix for mul
 * efeymul=caffeine
 * ebteupimul=dentine
 * avul=bread
 * ebavul=sandwich
 * nyefavul=waffle
 * oyebavul=crust
 * yuzavul=wrap, taco, gyro
 * zyiavul=pizza, pita, pide, flat bread
 * zyuavul=roll, bun, pastry roll
 * bokul=poison
 * bakul=medecine
 * jaovbakul=vaccine
 * leyavul=cake
 * leavul=dough
 * nyov leavul=noodle
 * niv leavul=spaghetti
 * umleavul=cookie
 * gratayuxul=allergen
 * gyazyiavul=pancake
 * makilpul=electrolyte
 * mavugxul=flame retardant
 * loyanbalul=decongestant
 * lobokogrunuul=disinfectant
 * melfyiul=fertilizer
 * nofyigxul=starch
 * pobokul=toxin, venom
 * pelt ovbuxul=insect repellent
 * sul=chemical base
 * tavyul=feces
 * pat tavyul=bird lime
 * telefxul=appetizer
 * vyixul=soap
 * teupib vyixul=toothpaste
 * tospanuul=stimulant
 * tosyofxul=anesthetic
 * ovtabessaxul=antigen
 * okyiabxul=laxative
 * umxul=dessicant
 * valyujul=sealant
 * vixul=cosmetic
 * yoymovul=antifreeze
 * yuglaxul=tenderizer
 * zaybuxul=propellant
 * zoybuxul=repellent
 * yanul=paste, glue
 * sexyanul=mortar
 * yegaxlul=reagent
 * vyomul=ersatz
 * muk=mineral
 * mukmil=mineral water
 * muktun=minerology
 * multuna=minerological
 * multut=minerologist
 * mukxer=mineralize
 * mukxen=mineralization
 * mukxwa=mineralized
 * mukzyeg=mine
 * mukzyegen=mining
 * mukzyegut=miner
 * mukzegwa=mined
 * nazmuk=ore
 * mug=metal
 * muga=metalic
 * mugayef=foil, metal sheet
 * drayefmug=sheet metal
 * mugnyem=metal case
 * nasmug=coin
 * mugnyif=metal cable
 * mugzyuv=metal rod, metal bar
 * mugyuvar=metal chain
 * mugmef=bar, ingot
 * mugfuv=bolt
 * mug goblar=hacksaw
 * mugneaf=wire mesh
 * mugnef=grate, grid, grill, griddle
 * mugnuf=metal button, stud
 * mugsiun=token
 * mugyaf=clasp, buckle
 * mugyafer=buckle up
 * mugyafwa=buckled up
 * mugsim=metal chair
 * mugyex=metallurgy
 * mugyexa=metallurgical
 * mugyexut=metallurgist
 * mugzyeg=nut
 * yanmug=alloy
 * mup=tunnel, tube, subway
 * muper=to tunnel
 * mupen=tunneling
 * mupur=subway train
 * mupuram=subway station
 * mupurnad=subway line
 * muf=stick, rod
 * mufag=post
 * mimufag=mast
 * mufyag=pole, boom
 * mufyeg=pipe
 * mufyegyan=piping
 * izmuf=arrow
 * dopuz-ismuf=bow-and-arrow
 * puxrer izmuf=shoot an arrow
 * ofmuf=barrier, bar
 * muv=cane, stick
 * adebmuv=scepter
 * edebmuv=royal mace, staff
 * fyatyezmuv=wand
 * izmuv=needle
 * tyoyamuv=cane
 * muz=precious metal, precious ore
 * muzkexut=prospector:

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

title: Mirad Thesaurus/Nature


text:
Applied Programming/Lists and Tuples

What is it?
A way in which data are stored for efficient search and retrieval. Different data structures are suited for different problems. Some data structures are useful for simple general problems, such as retrieving data that has been stored with a specific identifier. For example, an online dictionary can be structured so that it can retrieve the definition of a word. On the other hand, specialized data structures have been devised to solve complex specific search problems.

Looking at basic examples is an effective way to understand data structures. For example, a very basic example of a data structure is an array, in which multiple data bits are coordinated into a group sharing a common label. This helps programs call these data bits or perform other work on the data set as a whole. Another example of a data structure is a stack, which places data units in relative hierarchies, allowing code functions to work on the data in coordinated ways, such as pushing a new data unit into a stack, or popping a data unit from the top of a stack.

In a general sense, the data structure concept dovetails with that of virtual objects and virtual reality. As data is more elaborately arranged by developers and others, the data becomes more functional, allowing the emergence of a virtual reality. This is a core concept of many technological advances from the last few decades.

What is it?
In computer science, an array data structure, or simply an array, is a data structure consisting of a collection of elements (values or variables), each identified by at least one array index or key. An array is stored such that the position of each element can be computed from its index tuple by a mathematical formula. The simplest type of data structure is a linear array, also called one-dimensional array. Arrays are among the oldest and most important data structures, and are used by almost every program. They are also used to implement many other data structures, such as lists and strings. Arrays are useful mostly because the element indices can be computed at run time. Among other things, this feature allows a single iterative statement to process arbitrarily many elements of an array. For that reason, the elements of an array data structure are required to have the same size and should use the same data representation.

Indexing
Zero-based

Index starts with 0. Array length is equal to the number of elements the array can store. Zero-based arrays are zero-based because of math-related reasons. Not for hardware-related reasons.

One-based

Index starts with 1.

N-based

The base index of an array can be freely chosen. Usually programming languages allowing n-based indexing also allow negative index values and other scalar data types like enumerations, or characters may be used as an array index.

Dimensions
One-dimensional

A one-dimensional array (or single dimension array) is a type of linear array. Accessing its elements involves a single subscript which can either represent a row or column index. Output: Tues

Two-dimensional

Two dimensional array is an array within an array. It is an array of arrays. In this type of array the position of an data element is referred by two indices instead of one. So it represents a table with rows and columns of data.

Output: [11, 12, 5, 2] 10

Tuples
A tuple is a data structure that is an immutable, or unchangeable, ordered sequence of elements. Because tuples are immutable, their values cannot be modified.

Cannot modify

Output: TypeError: 'tuple' object does not support item assignment

As a general rule, tuples use less memory than a list or array.

Tuples allows for slicing and indexing like lists, but do not have methods for deleting or changing any elements.

Indexing Output: b e

Slicing Output: ('b', 'c', 'd', 'e') ('a', 'b') ('b', 'c') ('a', 'c', 'e')

Activities
1) Create a program that compares two lists and returns "True" if those lists have at least one common element.

2) Create a program that compares two lists and identifies common elements. Display the index of these common elements for each list.

3) Create a program that reads a list and removes any consecutive and repeating elements. For example, ["A", "B", "C", "C", "D", "E", "E", "G", "E", "F"] would result in ["A", "B", "C", "D", "E", "G", "E", "F"].

4) Create a program that combines two lists into a single list by alternating elements from each list. For example ["A", "B", "C"] + ["1", "2", "3"] would result in ["A", "1", "B", "2", "C", "3"].

Key Terms
Array (list) - A data structure consisting of a collection of elements (values or variables), each identified by at least one array index or key.

Data structure - A collection of data values, the relationships among them, and the functions or operations that can be applied to the data.

Field - A particular piece of data encapsulated within a class or object.

Hash table -A type of data structure that stores key-value pairs. The key is sent to a hash function that performs arithmetic operations on it. The result (commonly called the hash value or hash) is the index of the key-value pair in the hash table.

Heap - A specialized tree-based data structure that satisfies the heap property: if P is a parent node of C, then the key (the value) of P is either greater than or equal to (in a max heap) or less than or equal to (in a min heap) the key of C.

Index (key) - A numerical representation of an item's position in a sequence.

Linked list - A collection of elements called nodes, where each node has a value and points to the next node in the list (and sometimes the previous).

Member - A single datum of a record; for example, the 'Name' field of a 'Person' record.

Record (struct) - A structure used to collect multiple variables, often of different types stored as fields.

Tagged union - A union that contains one additional field indicating the current type for enhanced type safety.

Tuple - Similar to an array or list with the exception that they are immutable and enclosed in parentheses.

Union - A data structure where a number of primitive types may be stored in concert, similar to a struct or a record.

title: Applied Programming/Lists and Tuples


text: User talk:Landoffools

title: User talk:Landoffools


text:
Template:Wikijunior:Dinosaur Alphabet

-- A B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z --

title: Template:Wikijunior:Dinosaur Alphabet


text: Category:Book:Wikijunior:Dinosaur Alphabet


text:
Category:Book:Wikijunior:Dinosaur Alphabet/Templates

This category contains templates used in the Wikijunior:Dinosaur Alphabet book.


text: User talk:Ollz272

title: User talk:Ollz272


text:
User:PeterGrecian

mostly on en.wikipedia.org but am interested in contributing here where I can. PeterGrecian (discuss • contribs) 12:19, 10 March 2021 (UTC)

title: User:PeterGrecian


text:
Oberon/ETH Oberon/PPPHDLC.Mod

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) (* $VCS  1, Edgar.Schwarz@z.zgs.de, 28 Feb 99, 22:13:54 $ *) MODULE PPPHDLC;	(** non-portable *) (* $Log$ $  1, Edgar.Schwarz@z.zgs.de, 28 Feb 99, 22:13:54 version for PPP 1.0.0 *) IMPORT Debug := PPPDebug, SYSTEM, T:=PPPTools, (*es*) Oberon, Ker:=Kernel, V24, PT := NetBase, Input, Out, Strings; (* Ker:=PPCXOKernel, P:=Peripherals; *) CONST HDLCAddress=0FFX; HDLCControl=03X; HDLCHeaderLen* = 4;	(* Flag + Address, Protocol (2 Byte) *) EscSymbol = 7DX; FlagSymbol = 7EX; MTU*=1500; StartPos*=4;	(* even if we received a packed Packet, we can send back an unpacked one, using the same array *) ArrayLength* = MTU+100;	(* some bytes more needed *) TYPE Params* = POINTER TO ParamsDesc; ParamsDesc* = RECORD END; CallbackProc*=PROCEDURE (p:Params); TimeOut = POINTER TO TimeOutDesc; TimeOutDesc = RECORD time: LONGINT; callback: CallbackProc;	params: Params; next: TimeOut; END; PPPUnit* = POINTER TO PPPUnitDesc; MyTask* = POINTER TO MyTaskDesc; MyTaskDesc = RECORD (*es*) (Oberon.TaskDesc) (* (Ker.MainEventDesc) (* Oberon.TaskDesc *) *) Config*:PPPUnit; END; PPPUnitDesc* = RECORD MTU*, MRU*:INTEGER;		(* Maximum Transmit Unit, how big our packets are; M Receive U, how big he may send*) SendAsyncMap*:SET;		(* Transmit AsyncMap; What characters have to be stuffed *) (*es*) c*: LONGINT; (* c*: P.SerialChannel; *) cname*:ARRAY 32 OF CHAR; task*: MyTask; data, data2*: ARRAY ArrayLength OF CHAR; TOqueue: TimeOut; TOempty: BOOLEAN; END; VAR (*es*) debug*: BOOLEAN; TOtask: Oberon.Task; (* check for timeout *) TOunit: PPPUnit; (* instead of extending task *) (*TOrecycle: TimeOut;*) FrameCount: INTEGER; (* pe: number frames for reference. *) (*es*) (* Save incomplete frames between calls to Receive *) receiveFrame: RECORD active: BOOLEAN; (* ready to receive data *) (*deadline: LONGINT; (* until we want to receive the end *)*) i: INTEGER; (* index of last received byte in receive buffer *) esc: BOOLEAN; (* last byte received was EscSymbol *) END; (**)PPPHandleReceive*: PROCEDURE (U:PPPUnit; prot:INTEGER; VAR p: ARRAY OF CHAR; 			pos, len:INTEGER; VAR prno: INTEGER; VAR item: PT.Item); PROCEDURE SendString(c: (*es*)LONGINT(*P.SerialChannel*); 												VAR s: ARRAY OF CHAR); VAR l0, l1, start: LONGINT; (*es*)res: LONGINT;(**) BEGIN l0 := 0; WHILE s[l0] # 0X DO INC(l0) END; l1 := l0; start := 0; (*es*) WHILE l0 > 0 DO 			V24.SendBytes(c, s, l1, res); DEC(l0, l1); END (*	WHILE l0 > 0 DO 			c.Write(s, start, l1); 			DEC(l0, l1); INC(start, l1) 		END *) END SendString; (* Init *) PROCEDURE Init* (Config:PPPUnit; 									c:(*es*)LONGINT(* P.SerialChannel*);  						VAR cname, sstr, loginname, loginpasswd: ARRAY OF CHAR); VAR to:TimeOut; l: LONGINT; temp: ARRAY 4 OF CHAR; cr: ARRAY 2 OF CHAR; (*es*)res: LONGINT;(**) BEGIN Config.c := c; COPY(cname, Config.cname); (*es??? die V24 und Loginsachen macht doch der Dialer. Oder ? 	(* V24 login is handled by the Dialer, isn't it? *) 		WHILE V24.Available(c) > 0 DO V24.Receive(c, temp[0],res); END; 		(* WHILE c.Available > 0 DO l := 1; c.Read(temp, 0, l) END; *) 		(* send start string *) 		IF sstr[0] # 0X THEN 			SendString(c, sstr); 			(* consume some bytes (they contain the reply string from server) *) 			REPEAT 				WHILE c.Available > 0 DO l := 1; c.Read(temp, 0, l) END; 				Ker.Sleep(1, Ker.ONEsec) 			UNTIL c.Available = 0 		END; 		IF loginname[0] # 0X THEN	(* start normal unix-login procedure *) 			cr[0] := 0DX; cr[1] := 0X; 			(* send two CR *) 			SendString(c, cr); Ker.Sleep(1, Ker.ONEsec); 			SendString(c, cr); Ker.Sleep(5,Ker.ONEsec); 			(* send loginname *) 			SendString(c, loginname); SendString(c, cr); 			Ker.Sleep(1, Ker.ONEsec); 			(* send loginpasswd *) 			SendString(c, loginpasswd); SendString(c, cr); 			Ker.Sleep(1, Ker.ONEsec); 		END; 		REPEAT 			WHILE c.Available > 0 DO  				l := 1; c.Read(temp, 0, l); Debug.Int(ORD(temp[0]),4); IF (temp[0] >= 20X) & (temp[0] <= 7FX) THEN Debug.Char(9X); Debug.Char(temp[0]) END; Debug.Ln; END; Ker.Sleep(5,Ker.ONEsec); Debug.Ln; UNTIL c.Available = 0; es*) 		Debug.String("Starting receiving-loop"); Debug.Ln; 		NEW(Config.task); Config.task.Config:=Config;	 		(*es???*) Debug.String("Pustekuchen, macht Devicepolling"); Debug.Ln; 		(* pe *) Debug.String("Begin communicating with the remote system."); Debug.Ln; 		Debug.String("Configure the timeout."); Debug.Ln; 		(*Ker.InitMain(Config.task);*) 		NEW(to); Config.TOqueue:=to; to.next:=to; 		to.time:=MAX(LONGINT); Config.TOempty:=TRUE;	(* sentinel *) 	END Init; 	PROCEDURE CheckTimer((*es*)me: Oberon.Task(*C: PPPUnit*)); 	(* Called only when TOqueue is not empty *) 		VAR cur:TimeOut; 	BEGIN 		cur:=(*es*)TOunit(*C*).TOqueue;  		IF cur.time < (*es*)Input.Time(*Ker.Time*) THEN   (*es*)  Oberon.Remove(me);  			IF TOunit.cname # "" THEN 				(* output only if ppp is still running. See PPPMain.StopInst *) 				Out.String("PPP timeout"); Out.Ln; 			END; (**) 			(*es*)TOunit(*C*).TOempty:=TRUE; 			cur.callback(cur.params); 		END 	END CheckTimer; 	(* TimeOut Handling *) 	PROCEDURE TIMEOUT* (C: PPPUnit; callb:CallbackProc; p:Params; msec:LONGINT); (* msec: in microS-sec *) 	VAR cur:TimeOut; 	BEGIN 		cur:=C.TOqueue; cur.callback:=callb; cur.params:=p; 		cur.time:=(*es*) Input.Time(*Ker.Time*)+msec;	 		C.TOempty:=FALSE; 		(*es install timer task *) 		TOtask.safe := FALSE; TOtask.time := 0; 		TOtask.handle := CheckTimer; 		Oberon.Install(TOtask); 		TOunit := C; 		(**) 	END TIMEOUT; 	PROCEDURE UNTIMEOUT* (C: PPPUnit; callb:CallbackProc); 	BEGIN	 		C.TOempty:=TRUE; 		(*es*) Oberon.Remove(TOtask); (**) 	END UNTIMEOUT; 	(* CheckPacket - Check  a HDLC-Packet *) 	PROCEDURE CheckPacket(Config: PPPUnit; VAR p: ARRAY OF CHAR; pos, len:INTEGER; VAR prno: INTEGER; VAR item: PT.Item);    (*es*)VAR timeStr: ARRAY 16 OF CHAR; time, date: LONGINT;(**) 	BEGIN 		IF debug THEN 			(* pe *) Debug.String('->->-> Frame '); Debug.Int(FrameCount, 5);  			Debug.String(' received from peer.'); Debug.Ln; 			INC(FrameCount); (* pe *) 			Oberon.GetClock(time, date); 			Strings.TimeToStr(time,timeStr);  			Debug.String(timeStr);  			Debug.String('CheckPacket: len = '); Debug.Int(len, 5); Debug.Ln;  			T.OutPacket(p, pos, len); 		END; 		IF len > HDLCHeaderLen+2 THEN  			(*[HDLC_Address+HDLC-Control+Protocol] + Checksum (2 Bytes)*) 			IF T.CheckFCS(p, pos, len) THEN  				(* CheckSum ok? The whole packet needed! *) 				IF (p[pos] = HDLCAddress) & (p[pos+1] = HDLCControl) THEN 					PPPHandleReceive(Config, T.GetInt(p, pos+2), p, pos+4, len-6, prno, item); 				ELSE (* silently discarded *) 					IF debug THEN 						Debug.String("Address, Code wrong"); Debug.Ln;  					END; 				END 			ELSE 				IF debug THEN Debug.String("Checksum failure"); Debug.Ln END 			END 		ELSE  			IF debug & (len > 0) THEN  				Debug.String("Length too short, length: ");  				Debug.Int(len, 6); Debug.Ln;  			END; 		END 	END CheckPacket; 	PROCEDURE XOR20(ch:LONGINT):LONGINT; 	BEGIN RETURN SYSTEM.VAL(LONGINT, (SYSTEM.VAL(SET, ch) / {5} )); 	END XOR20; 	(* ReceivePacket - ReceiveLoop: Task, needs extended Event (including PPPUnit)*) (*es*) (* ReceivePacket is indirectly called by NetBase.Polldevices when characters at the serial interface are available. So just read the characters into a buffer (Config.data) and return prno=0 (no handler installed for this 	protocol hopefully). When you get end of frame (FlagSymbol) then check it and return the stuff. *) (**)PROCEDURE ReceivePacket*(Config: PPPUnit; VAR prno: INTEGER; VAR item: PT.Item); 	VAR (*es*) (*i:INTEGER;*) 		ch: ARRAY 4 OF CHAR; l: LONGINT; 		(*es*)c, res, endTime: LONGINT; timeOut : TimeOut; 		(* c: P.SerialChannel; *) 	BEGIN 		c:=Config.c; 		(*es*)(* i:=StartPos; ch[0]:=0X;	(* not Esc-Symbol *) *) (*es*)IF receiveFrame.active THEN 			prno := 0; 		ELSE 			(*receiveFrame.deadline := Input.Time + 10(*s*) * Input.TimeUnit;*) 			receiveFrame.i := StartPos; 			receiveFrame.active := TRUE; 			receiveFrame.esc := FALSE; 			ch[0]:=0X; 		END; 		IF receiveFrame.esc THEN ch[0] := EscSymbol ELSE ch[0]:=0X; END; (**) LOOP 			IF (*es*)V24.Available(c)(*c.Available*)>0 THEN		 				(* New chars in buffer ? *) 				IF ch[0] (* last received *) #EscSymbol THEN 					(*es*) V24.Receive(c, ch[0], res); 					(*l := 1; c.Read(ch, 0, l);*) 					IF ch[0] = FlagSymbol THEN (* end of frame received *) 						CheckPacket(Config, Config.data, StartPos, receiveFrame.i-StartPos, prno, item); (*es*)			 (* data now in item *) receiveFrame.active := FALSE; RETURN; 						(* receiveFrame.i:=StartPos; *) 					ELSE 						IF ch[0] # EscSymbol THEN  							Config.data[receiveFrame.i]:=ch[0];  							INC(receiveFrame.i) ; (*es*)				 receiveFrame.esc := FALSE; 						ELSE 							receiveFrame.esc := TRUE; (**) 				END 					END; 				ELSE 					(*es*) V24.Receive(c, ch[0], res); receiveFrame.esc := FALSE; 					(*l := 1; c.Read(ch, 0, l);*) 					Config.data[receiveFrame.i]:=CHR(XOR20(ORD(ch[0]))); 					INC(receiveFrame.i); ch[0]:=0X; (* not Esc-,or Flag-Symbol *) 				END; 				IF receiveFrame.i>=ArrayLength THEN  					Debug.String("Array Overflow!!");  					 (* HALT(99); *)  					receiveFrame.active := FALSE; RETURN 				END; 			ELSE 				RETURN; (* pause until more characters are available *) (**) 			END; 		END 	END ReceivePacket; 	(* SendPacket - Send a packet to the V24 *) PROCEDURE SendPacket* (Config: PPPUnit; prot:INTEGER; 						VAR p:ARRAY OF CHAR; pos, len:INTEGER); VAR minpos, code, k, begin: INTEGER; ch: ARRAY 4 OF CHAR; l0, l1, start: LONGINT; x: CHAR; (*es*)c, res: LONGINT; timeStr: ARRAY 16 OF CHAR; time, date: LONGINT; (*c: P.SerialChannel;*) BEGIN c:=Config.c; 		minpos:=HDLCHeaderLen; IF pos<minpos THEN T.CopyString(p, pos, minpos, len); pos:=minpos; END;	(* More space needed *) DEC(pos, HDLCHeaderLen); INC(len, HDLCHeaderLen); p[pos]:=0FFX; p[pos+1]:=03X;		(* pos + 0: HDLC_Address = 0FFX; pos + 1: HDLC_Control =3X *) T.PutInt(prot, p, pos+2);				(* pos + 2: Protocol *) code:=T.CalcFCS(p, pos, len); p[pos+len]:=CHR(code MOD 256); p[pos+len+1]:=CHR(SYSTEM.LSH(code, -8)); INC(len, 2); (* insert the checksum *) IF debug THEN (* pe *) Debug.String('<-<-<- Frame '); Debug.Int(FrameCount, 5); Debug.String(' going to peer.'); Debug.Ln; INC(FrameCount); (* pe *) Oberon.GetClock(time, date); Strings.TimeToStr(time,timeStr); Debug.String(timeStr); Debug.String(' SendPacket: len = '); Debug.Int(len, 5); Debug.Ln; T.OutPacket(p, pos, len); Debug.Ln 		END; (* send it to the V24 *) ch[0]:=FlagSymbol; l0 := 1; l1 := l0; start := 0; WHILE l0 > 0 DO 			(*es*)V24.Send(c,ch[start], res); (* c.Write(ch, start, l1); *) DEC(l0, l1); INC(start, l1) END; (* es auskommentiert: der Trick ist irgendwie alle Zeichen zu sammeln, 	die man ohne Maskierung (EscSymbol) senden kann. Wenn man dann 	auf eines trifft, verpackt man es und schickt die Dinger von zuvor 	auf weg. Das ist mir etwas zu undurchsichtig. 	Translation & remark from T.F.  	Section commented out: The trick is to somehow collect all the  	characters that can be sent without escaping (EscSymbol).  Once we  	come across a character that needs escaping, we send all the previously  	collected characters followed by the escaped character.  	It is probably some kind of "optimized code" that was translated and when  	it did not work was finally replaced by the version below the  	commented-out code.  From what I can tell the active code is better  	anyways (simpler).  If optimization is needed, AosIO could be used to collect  	the characters in a much simpler way. *) (*	begin:=pos; 		FOR k:=pos TO pos+len-1 DO	x:=p[k]; 			IF ((ORD(x)<20H) & (ORD(x) IN Config.SendAsyncMap)) 			OR (x=EscSymbol) OR (x=FlagSymbol) THEN 				l0 :=k-begin; l1 := l0; start := begin; 				WHILE l0 > 0 DO c.Write(p, start, l1); DEC(l0,l1); INC(start,l1);END; 				begin:=k+1; 				ch[0]:=EscSymbol; ch[1]:=CHR(XOR20(ORD(x)));  				l0 := 2; l1 := l0; start := 0; 				WHILE l0 > 0 DO c.Write(ch, start, l1); DEC(l0,l1); INC(start,l1);END;  			END; 		END; 		p[pos+len]:=FlagSymbol; l0 := pos+len+1-begin; l1 := l0; start := begin;  		WHILE l0 > 0 DO c.Write(p, start, l1); DEC(l0, l1); INC(start, l1); END; *) (*es*) FOR k:=pos TO pos+len-1 DO 			x:=p[k]; IF ((ORD(x)<20H) & (ORD(x) IN Config.SendAsyncMap)) OR (x=EscSymbol) OR (x=FlagSymbol) THEN V24.Send(c,EscSymbol, res); IF res # 0 THEN HALT(99); END; V24.Send(c,CHR(XOR20(ORD(x))), res); IF res # 0 THEN HALT(99); END; ELSE V24.Send(c, x, res); IF res # 0 THEN HALT(99); END; END; END; (* frame complete: send end flag *) V24.Send(c,FlagSymbol, res); IF res # 0 THEN HALT(99); END; (**) 	END SendPacket; BEGIN (* pe *) FrameCount := 0; debug := FALSE; (*es*) receiveFrame.active := FALSE; NEW(TOtask); (*NEW(TOrecycle); TOrecycle.next:=TOrecycle; (* Sentinel *)*) END PPPHDLC.

title: Oberon/ETH Oberon/PPPHDLC.Mod


text:
AQA A-Level Physics/Binding Energy

Key Ideas
If one were to separate a nucleus into its individual nucleons, work must be done to overcome the strong force holding the nucleons together. The binding energy of a nucleus is the work that must be done to separate a nucleus into its constituent neutrons and protons.

When a nucleus forms from nucleons, energy is released as the strong force does work by pulling the nucleons together. When nucleons are separated from a nucleus, energy is used to break the strong force.

However, because Albert Einstein proved that the mass of an object increases when it gains energy and decreases when it loses energy, the mass of a nucleus is less than the mass of the separated nucleons. This is because energy is released when the nucleons form the nucleus, so the mass decreases. This difference between the mass of the separated nucleons and the mass of the nucleus is called the mass defect.

You can use mass defect to calculate the energy released when the nucleus formed from the separate nucleons i.e. its binding energy.

Binding energy of a nucleus =  (△m)(c²)

Calculation of mass defect
When calculating mass defect (△m), you are subtracting the mass of the nucleus from the combined mass of the nucleons.

To calculate the mass defect, you need  the mass of the nucleus (MNUC), the mass of a proton (mp) the mass of a neutron (mn) and the number of protons (Z) and neutrons (A-Z, where A represents atomic number i.e. all nucleons). (Remember, electrons are not involved at any point in this calculation as we are only referring to the nucleus of the atom.)

mp = 1.67(3) x10 -27 kg

mn = 1.67(5) x10 -27 kg

Therefore, a generic formula for mass defect is:

mass defect, △m =  Z(mp) + (A - Z)(mn)  -  MNUC

title: AQA A-Level Physics/Binding Energy


text:
Oberon/ETH Oberon/PPPFSM.Mod

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) MODULE PPPFSM;	(** non-portable *) (* FSM = Finite State Machine; equivalent to "automaton" in RFC 1548. *) (* $VCS  2, Edgar.Schwarz@z.zgs.de, 5 Sep 99, 13:46:21 $     $Log$ $   2, Edgar.Schwarz@z.zgs.de, 5 Sep 99, 13:46:21 log message for echo reply addes $   1, Edgar.Schwarz@z.zgs.de, 28 Feb 99, 22:15:39 version for PPP 1.0.0 *) IMPORT HDLC := PPPHDLC, Debug := PPPDebug, Tools := PPPTools; CONST (** CP (LCP, IPCP, etc.) codes *) ConfReq* = 1;	(* configuration request *) ConfAck* = 2;	(* configuration ack *) ConfNak* = 3;	(* configuration nak *) ConfRej* = 4;	(* configuration reject *) TermReq = 5;	(* termination request *) TermAck = 6;	(* termination ack *) CodeRej = 7;	(* code reject *) ProtRej = 8; 	(* protocol reject *) EchoReq = 9; EchoReply = 10; (** Link states *) Initial* = 0;	(* down, hasn't been opened *) Starting* = 1;	(* down, been opened *) Closed* = 2;	(* up, hasn't been opened *) Stopped* = 3;	(* open, waiting for down event *) Closing* = 4;	(* Terminating the connection, not open *) Stopping* = 5;	(* terminating, but open *) ReqSent* = 6;	(* we've sent a config request *) AckRcvd* = 7;	(* we've received a config ack *) AckSent* = 8;	(* we've sent a config ack *) Opened* = 9;	(* connection available *) (** Flags *) Passive* = 0;	(* don't die if we don't get a response *) Restart* = 1;	(* treat second Open as Down, Up *) Silent* = 2;	(* wait for peer to speak first *) (** Timeouts *) DefTimeout* = 30000;	(* timeout time in milliseconds *) DefMaxTermReqs* = 2;	(* maximum terminate-request transmissions *) DefMaxConfReqs* = 10;	(* maximum configure-request transmissions *) DefMaxNakLoops* = 10;	(* maximum # of nak loops *) HeaderLen = 4;	(* code(1) + id(1) + len(2) = HeaderLen of a CP-Packet *) StartPos = HDLC.StartPos + HDLC.HDLCHeaderLen + HeaderLen; newtransmit = TRUE; retransmit = FALSE; StrLen* = 33; TYPE Params = POINTER TO ParamsDesc; FSM* = POINTER TO FSMDesc; FSMDesc* = RECORD Protocol*: INTEGER;	ProtoName*: ARRAY 32 OF CHAR; State*: SHORTINT; Flags*: SET; ID*, reqID*: SHORTINT;	(* unsigned char *) TimeoutTime: LONGINT; MaxConfReqTransmits*, Retransmits*, MaxTermTransmits*, NakLoops*, MaxNakLoops*: INTEGER; (* Callback Procedures *) ResetCI*: PROCEDURE (f: FSM); CILen*: PROCEDURE (f: FSM): INTEGER; AddCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos: INTEGER; VAR len: INTEGER); AckCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; NakCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; RejCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; ReqCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; VAR pos, len: INTEGER; mode: BOOLEAN): SHORTINT; Up*: PROCEDURE (f: FSM); Down*: PROCEDURE (f: FSM); (*		Starting*: PROCEDURE (f: FSM); *) (*		Finished*: PROCEDURE (f: FSM); *) ExtCode*: PROCEDURE (f: FSM; code, id:SHORTINT; VAR inp: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; HDLCConfig*: HDLC.PPPUnit; params: Params; END; ParamsDesc = RECORD (HDLC.ParamsDesc) f:FSM END; String* = ARRAY StrLen OF CHAR; VAR ActTimeout*:LONGINT; ActMaxConfReqs*:INTEGER; PROCEDURE ^ Init* (f: FSM); PROCEDURE ^ LowerUp* (f: FSM); PROCEDURE ^ LowerDown* (f: FSM); PROCEDURE ^ Open* (f: FSM); PROCEDURE ^ Close* (f: FSM); PROCEDURE ^ Timeout (params: HDLC.Params); PROCEDURE ^ Input* (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveConfReq* (f: FSM; id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveConfAck* (f: FSM; id: SHORTINT; 						VAR p:  ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveConfNakRej* (f: FSM; code, id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveTermReq* (f: FSM; id: SHORTINT); PROCEDURE ^ ReceiveTermAck* (f: FSM); PROCEDURE ^ ReceiveCodeRej* (f: FSM; VAR p: ARRAY OF CHAR; 						pos, len: INTEGER); PROCEDURE ^ ProtReject* (f: FSM); PROCEDURE ^ SendConfReq* (f: FSM; retransmit: BOOLEAN); PROCEDURE ^ SendData* (f: FSM; code, id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE OutLog* (text1, text2:ARRAY OF CHAR; f:FSM) ; BEGIN Debug.String(text1); Debug.Ln; IF text2 # "" THEN Debug.String(text2); Debug.Ln; END; Debug.String("protocol: "); Debug.String(f.ProtoName); Debug.String(" -  channel: "); Debug.String(f.HDLCConfig.cname); Debug.Ln; END OutLog; PROCEDURE OutCode* (code: SHORTINT); BEGIN Debug.String("code: "); CASE code OF 		  ConfReq:	Debug.String("ConfReq") | ConfAck:	Debug.String("ConfAck") | ConfNak:	Debug.String("ConfNak") | ConfRej:	Debug.String("ConfRej") | TermReq:	Debug.String("TermReq") | TermAck:	Debug.String("TermAck") | CodeRej:	Debug.String("CodeRej") | ProtRej:	Debug.String("ProtocolRej") | EchoReply: Debug.String("EchoReply") ELSE	Debug.String("*** illegal code ***"); Debug.Int(code, 4); END; Debug.Ln END OutCode; PROCEDURE GiveState*(state: SHORTINT; VAR s: String); BEGIN CASE state OF 		  Initial:		s:="Initial";	| Starting:	s:="Starting"; | Closed:		s:="Closed";	| Stopped:	s:="Stopped"; | Closing:		s:="Closing"; | Stopping:	s:="Stopping"; | ReqSent:	s:="ReqSent";	| AckRcvd:	s:="AckRcvd"; | AckSent:	s:="AckSent"; | Opened:	s:="Opened"; ELSE	s:=" *** unknown state ***"; END; END GiveState; PROCEDURE OutState* (state: SHORTINT); VAR s: String; BEGIN Debug.String("state: "); GiveState(state, s); Debug.String(s); Debug.Ln END OutState; (* Init FSM *) PROCEDURE Init* (f: FSM); BEGIN f.State := Initial;	f.Flags := {};	f.ID := 0;	(* f.reqID set later *) f.TimeoutTime := ActTimeout; f.MaxConfReqTransmits := ActMaxConfReqs; f.MaxTermTransmits := DefMaxTermReqs; f.MaxNakLoops := DefMaxNakLoops; NEW(f.params); f.params.f:=f; END Init; (* The lower layer is up *) PROCEDURE LowerUp* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.LowerUp","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Initial:	f.State := Closed | Starting: IF Silent IN f.Flags THEN f.State := Stopped ELSE SendConfReq(f, newtransmit); f.State := ReqSent	(* send an initial configure-request *) END ELSE OutLog("FSM.LowerUp","ERROR: in wrong state",f); OutState(f.State); Debug.Ln; END END LowerUp; (* The lower layer is down - cancel all timeouts and inform upper layers *) PROCEDURE LowerDown* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.LowerDown","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Closed:	f.State := Initial | Stopped:	f.State := Starting (* ; f.Starting (f) *) | Closing:	f.State := Initial; HDLC.UNTIMEOUT(f.HDLCConfig, Timeout)	(* cancel timeout *) | Stopping, ReqSent, AckRcvd, AckSent:	f.State := Starting; HDLC.UNTIMEOUT(f.HDLCConfig, Timeout)	(* cancel timeout *) | Opened:	f.Down(f); f.State := Starting ELSE OutLog("FSM.LowerDown", "ERROR: in wrong state", f); OutState(f.State); Debug.Ln 	END END LowerDown; (* Link is allowed to come up *) PROCEDURE Open* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.Open","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Initial:	f.State := Starting; (* f.Starting(f) *) | Closed: IF Silent IN f.Flags THEN f.State := Stopped ELSE SendConfReq(f, newtransmit); f.State := ReqSent;	(* send an initial configure-request *) END | Closing:	f.State := Stopping; IF Restart IN f.Flags THEN LowerDown(f); LowerUp(f) END | Stopped, Opened:	IF Restart IN f.Flags THEN LowerDown(f); LowerUp(f) END ELSE END END Open; (* Start closing connection *) PROCEDURE Close* (f: FSM); VAR p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF HDLC.debug THEN OutLog("FSM.Close","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Starting:	f.State := Initial | Stopped:	f.State := Closed | Stopping:	f.State := Closing | ReqSent, AckRcvd, AckSent, Opened: IF f.State # Opened THEN HDLC.UNTIMEOUT(f.HDLCConfig, Timeout)	(* cancel timeout *) ELSE f.Down(f)	(* inform upper layers we're down *) END; f.Retransmits := f.MaxTermTransmits; INC(f.ID); f.reqID := f.ID; SendData(f, TermReq, f.reqID, p, StartPos, 4); HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime); DEC(f.Retransmits); f.State := Closing ELSE END END Close; (* Timeout expired *) PROCEDURE Timeout (params: HDLC.Params); VAR f: FSM; BEGIN f := params(Params).f; 	IF HDLC.debug THEN OutLog("FSM.TimeOut","TimeOut-Handler called",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Closing, Stopping: IF f.Retransmits <= 0 THEN	(* we've waited for an ack long enough, peer probably heard us *) IF f.State = Closing THEN f.State := Closed ELSE f.State := Stopped END; (* f.Finished(f) *) ELSE	(* send terminate-request *) INC(f.ID); f.reqID := f.ID; SendData(f, TermReq, f.reqID, f.HDLCConfig.data2, StartPos, 0); HDLC.TIMEOUT(f.HDLCConfig, Timeout, params, f.TimeoutTime); DEC(f.Retransmits) END | ReqSent, AckRcvd, AckSent: IF f.Retransmits <= 0 THEN OutLog("LOG: FSM.Timeout", "Stop: sended all TimeOuts, no answer", f); Debug.Ln; f.State := Stopped; (* IF ~(Passive IN f.Flags) THEN f.Finished(f) END *) ELSE	(* retransmit the configure-request *) SendConfReq(f, retransmit); IF f.State = AckRcvd THEN f.State := ReqSent END END ELSE IF HDLC.debug THEN OutLog("FSM.Timeout", "ERROR:in wrong state", f); OutState(f.State); Debug.Ln; END END END Timeout; (* Input packet *) PROCEDURE Input* (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR code, id: SHORTINT; size: INTEGER; BEGIN (* parse header (code, id and length). if packet too short, drop it. *) IF HDLC.debug THEN (* pe: "FSM.ReceiveData" was followed by redundant report "new Input". *) OutLog("FSM.ReceiveData","",f); OutState(f.State); Debug.Ln; Tools.OutPacket(p, pos, len); Debug.Ln; END; IF len < HeaderLen THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received short header", f); END; RETURN END; code := SHORT(ORD(p[pos])); id := SHORT(ORD(p[pos + 1])); size := Tools.GetInt(p, pos + 2); IF size < HeaderLen THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received illegal length", f); END; RETURN END; IF size < len THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received short packet", f); END; RETURN END; DEC(size, HeaderLen); INC(pos, HeaderLen); IF (f.State = Initial) OR (f.State = Starting) THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received packet in wrong state", f); OutState(f.State); Debug.Ln; END; RETURN END; (* action depends on code *) CASE code OF 		  ConfReq:	ReceiveConfReq(f, id, p, pos, size) | ConfAck:	ReceiveConfAck(f, id, p, pos, size) | ConfNak, ConfRej:	ReceiveConfNakRej(f, code, id, p, pos, size) | TermReq:	ReceiveTermReq(f, id) | TermAck:	ReceiveTermAck(f) | CodeRej:	ReceiveCodeRej(f, p, pos, size) ELSE IF ~f.ExtCode(f, code, id, p, pos, size) THEN INC(f.ID); SendData(f, CodeRej, f.ID, p, pos - HeaderLen, size + HeaderLen) END END END Input; (* Receive Configure-Request *) PROCEDURE ReceiveConfReq* (f: FSM; id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR code: SHORTINT; RejectIfDisagree: BOOLEAN; BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveConfigureRequest", "", f); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln 	END; CASE f.State OF 		  Closed:	SendData(f, TermAck, id, p, StartPos, 0); RETURN	(* go away, we're closed *) | Closing, Stopping:	RETURN | Opened:	f.Down(f); SendConfReq(f, newtransmit) (* go down and restart negotiation, inform upper layers, 					send initial configure-request *) | Stopped:	SendConfReq(f, newtransmit); f.State := ReqSent; (* send initial configure-request *) ELSE END; (* pass the requested configuration options to protocol-specific code for checking *) RejectIfDisagree := f.NakLoops >= f.MaxNakLoops; code := f.ReqCI(f, p, pos, len, RejectIfDisagree); (* send the Ack, Nak or Rej to the peer *) SendData(f, code, id, p, pos, len); IF code = ConfAck THEN IF f.State = AckRcvd THEN HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); f.State := Opened; f.Up(f) ELSE f.State := AckSent; f.NakLoops := 0 END ELSE	(* we sent ConfAck or ConfRej *) IF f.State # AckRcvd THEN f.State := ReqSent END; IF code = ConfNak THEN INC(f.NakLoops) END; END END ReceiveConfReq; (* Receive Configure-Ack *) PROCEDURE ReceiveConfAck* (f: FSM; id: SHORTINT; VAR p: ARRAY OF CHAR; pos, len: INTEGER); BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveConfAck", "", f); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln END; IF (id=f.reqID) & f.AckCI(f, p, pos, len) THEN f.reqID := -1; CASE f.State OF 			  Closed, Stopped:	SendData(f, TermAck, id, p, StartPos, 0) | ReqSent:	f.State := AckRcvd; f.Retransmits := f.MaxConfReqTransmits | AckRcvd:	SendConfReq(f, newtransmit); f.State := ReqSent	(* huh?, an extra Ack? oh well... *) | AckSent:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout);	(* cancel timeout *) f.State := Opened; f.Retransmits := f.MaxConfReqTransmits; f.Up(f) | Opened:	(* go down and restart negotiation *) f.Down(f); SendConfReq(f, newtransmit); f.State := ReqSent ELSE END END END ReceiveConfAck; (* Receive Configure-Nak or Configure-Reject *) PROCEDURE ReceiveConfNakRej* (f: FSM; code, id: SHORTINT; 	VAR p: ARRAY OF CHAR; pos, len: INTEGER); BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveConfigureNak/Reject", "", f); Debug.String("id = "); Debug.Int(id, 4); Debug.String(",   reqID = "); Debug.Int(f.reqID, 4); Debug.Ln; Debug.Ln 	END; IF id # f.reqID THEN RETURN END;	(* expected ID? nope -> toss... *) IF ((code = ConfNak) & ~f.NakCI(f, p, pos, len)) OR ((code=ConfRej) & ~f.RejCI(f, p, pos, len)) THEN (* Nak/Reject is bad - ignore it *) IF HDLC.debug THEN OutLog("FSM.ReceiveConfNakRej", "ERROR: Received bad Nak/Rej", f); Debug.String("id: "); Debug.Int(f.ID, 4); Debug.Ln; OutCode(code); Debug.Ln; RETURN END END; f.reqID := -1; CASE f.State OF 		  Closed, Stopped:	SendData(f, TermAck, id, p, StartPos, 0) | ReqSent, AckSent:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); SendConfReq(f, newtransmit) (* They didn't agree to what we wanted - try another request *) (*(*pe*)	SendConfReq(f, retransmit) *) | AckRcvd:	SendConfReq(f, newtransmit); f.State := ReqSent	(* got a Nak/Reject when we had already had an Ack?? oh well... *) | Opened:	(* go down and restart negotiation *) f.Down(f); SendConfReq(f, newtransmit); f.State := ReqSent ELSE END END ReceiveConfNakRej; (* Receive Terminate-Request *) PROCEDURE ReceiveTermReq* (f: FSM; id: SHORTINT); VAR p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveTermReq", "", f); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln END; CASE f.State OF 		  AckRcvd, AckSent:	f.State := ReqSent | Opened: OutLog("FSM.ReceiveTermReq", "Terminated at peer's request", f); f.Down(f); f.Retransmits := 0; f.State := Stopping; HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime) ELSE END; SendData(f, TermAck, id, p, StartPos, 0) END ReceiveTermReq; (* Receive Terminate-Ack *) PROCEDURE ReceiveTermAck* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveTermAck", "", f); Debug.Ln; END; CASE f.State OF 		  Closing:	f.State := Closed (* ; IF f.Finished # NIL THEN f.Finished(f) END *) | Stopping:	f.State := Stopped (* ; IF f.Finished # NIL THEN f.Finished(f) END *) | AckRcvd:	f.State := ReqSent | Opened:	f.Down(f); SendConfReq(f, newtransmit) ELSE END END ReceiveTermAck; (* Receive a Code-Reject *) PROCEDURE ReceiveCodeRej* (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR code, id: SHORTINT; BEGIN IF len < HeaderLen THEN IF HDLC.debug THEN OutLog("FSM.ReceiveCodeRej", "ERROR: too short", f); Debug.Ln; END; RETURN END; code := SHORT(ORD(p[pos])); id := SHORT(ORD(p[pos + 1]));	(* syslog *) IF HDLC.debug THEN OutLog("FSM.ReceiveCodeRej", "Received Code-Reject", f); OutCode(code); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln; END; IF f.State = AckRcvd THEN f.State := ReqSent END END ReceiveCodeRej; (* Peer doesn't speak this protocol - Treat this as a catastrophic error (RXJ-)*) PROCEDURE ProtReject* (f: FSM); VAR p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF HDLC.debug THEN OutLog("FSM.ProtReject", "", f); Debug.Ln; END; CASE f.State OF 		  Closing:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); f.State := Closed; (* IF f.Finished # NIL THEN f.Finished(f) END *) | Closed:	f.State := Closed; (* IF f.Finished # NIL THEN f.Finished(f) END *) | Stopping, ReqSent, AckRcvd, AckSent:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); f.State := Stopped (* ; IF f.Finished # NIL THEN f.Finished(f) END *) | Stopped:	f.State := Stopped (* IF f.Finished # NIL THEN f.Finished(f) END *) | Opened:	f.Down(f); (* init restart counter, send terminate-request *) f.Retransmits := f.MaxTermTransmits; INC(f.ID); f.reqID := f.ID; SendData(f, TermReq, f.reqID, p, StartPos, 0); HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime); DEC(f.Retransmits); f.State := Stopping ELSE IF HDLC.debug THEN OutLog("FSM.ProtReject", "ERROR: in wrong state", f); OutState(f.State); Debug.Ln END END END ProtReject; (* Send a Configure-Request *) PROCEDURE SendConfReq* (f: FSM; retransmit: BOOLEAN); VAR pos: INTEGER; CILen: INTEGER; p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF (f.State # ReqSent) & (f.State # AckRcvd) & (f.State # AckSent) THEN (* not currently negotiating - reset options *) f.ResetCI(f); f.NakLoops := 0 END; IF retransmit THEN (* new request - reset transmission counter, use new ID *) f.Retransmits := f.MaxConfReqTransmits; INC(f.ID); f.reqID := f.ID 	END; IF HDLC.debug THEN OutLog("FSM.SendConfReq", "", f); Debug.String("id: "); Debug.Int(f.reqID, 4); Debug.String("   "); OutState(f.State); Debug.Ln END; (* make up a request packet *) pos := StartPos; IF f.CILen(f) < f.HDLCConfig.MTU - HeaderLen THEN f.AddCI(f, p, pos, CILen) ELSE OutLog("FSM.SendConfReq", "ERROR: Configure Request too big", f); RETURN END; (* send the request to our peer *) SendData(f, ConfReq, f.reqID, p, pos, CILen); (* start the retransmit timer *) DEC(f.Retransmits); HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime); END SendConfReq; (* SendData - Create a packet with code, id and data, 	data is in p[pos .. pos+len] *) PROCEDURE SendData* (f: FSM; code, id: SHORTINT; 												VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR minpos, maxlen: INTEGER; BEGIN maxlen:=f.HDLCConfig.MTU - HeaderLen; IF len > maxlen THEN len := maxlen; END; (* adjust length (of information + padding) to be smaller than MTU *) minpos:=HDLC.HDLCHeaderLen+HeaderLen; IF pos<minpos THEN Tools.CopyString(p, pos, minpos, len); pos:=minpos; END; DEC(pos, HeaderLen); INC(len, HeaderLen); p[pos]:=CHR(code); p[pos+1]:=CHR(id); Tools.PutInt(len, p, pos+2); IF HDLC.debug THEN OutLog("FSM.SendData", "", f); OutCode(code); OutState(f.State); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Tools.OutPacket(p, pos, len); Debug.Ln; END; HDLC.SendPacket(f.HDLCConfig, f.Protocol, p, pos, len); END SendData; BEGIN ActTimeout:=DefTimeout; ActMaxConfReqs:=DefMaxConfReqs END PPPFSM.

title: Oberon/ETH Oberon/PPPFSM.Mod


text:
Oberon/ETH Oberon/PPPIPCP.Mod

(* ETH Oberon, Copyright 1990-2003 Computer Systems Institute, ETH Zurich, CH-8092 Zurich. Refer to the license.txt file provided with this distribution. *) MODULE PPPFSM;	(** non-portable *) (* FSM = Finite State Machine; equivalent to "automaton" in RFC 1548. *) (* $VCS  2, Edgar.Schwarz@z.zgs.de, 5 Sep 99, 13:46:21 $     $Log$ $   2, Edgar.Schwarz@z.zgs.de, 5 Sep 99, 13:46:21 log message for echo reply addes $   1, Edgar.Schwarz@z.zgs.de, 28 Feb 99, 22:15:39 version for PPP 1.0.0 *) IMPORT HDLC := PPPHDLC, Debug := PPPDebug, Tools := PPPTools; CONST (** CP (LCP, IPCP, etc.) codes *) ConfReq* = 1;	(* configuration request *) ConfAck* = 2;	(* configuration ack *) ConfNak* = 3;	(* configuration nak *) ConfRej* = 4;	(* configuration reject *) TermReq = 5;	(* termination request *) TermAck = 6;	(* termination ack *) CodeRej = 7;	(* code reject *) ProtRej = 8; 	(* protocol reject *) EchoReq = 9; EchoReply = 10; (** Link states *) Initial* = 0;	(* down, hasn't been opened *) Starting* = 1;	(* down, been opened *) Closed* = 2;	(* up, hasn't been opened *) Stopped* = 3;	(* open, waiting for down event *) Closing* = 4;	(* Terminating the connection, not open *) Stopping* = 5;	(* terminating, but open *) ReqSent* = 6;	(* we've sent a config request *) AckRcvd* = 7;	(* we've received a config ack *) AckSent* = 8;	(* we've sent a config ack *) Opened* = 9;	(* connection available *) (** Flags *) Passive* = 0;	(* don't die if we don't get a response *) Restart* = 1;	(* treat second Open as Down, Up *) Silent* = 2;	(* wait for peer to speak first *) (** Timeouts *) DefTimeout* = 30000;	(* timeout time in milliseconds *) DefMaxTermReqs* = 2;	(* maximum terminate-request transmissions *) DefMaxConfReqs* = 10;	(* maximum configure-request transmissions *) DefMaxNakLoops* = 10;	(* maximum # of nak loops *) HeaderLen = 4;	(* code(1) + id(1) + len(2) = HeaderLen of a CP-Packet *) StartPos = HDLC.StartPos + HDLC.HDLCHeaderLen + HeaderLen; newtransmit = TRUE; retransmit = FALSE; StrLen* = 33; TYPE Params = POINTER TO ParamsDesc; FSM* = POINTER TO FSMDesc; FSMDesc* = RECORD Protocol*: INTEGER;	ProtoName*: ARRAY 32 OF CHAR; State*: SHORTINT; Flags*: SET; ID*, reqID*: SHORTINT;	(* unsigned char *) TimeoutTime: LONGINT; MaxConfReqTransmits*, Retransmits*, MaxTermTransmits*, NakLoops*, MaxNakLoops*: INTEGER; (* Callback Procedures *) ResetCI*: PROCEDURE (f: FSM); CILen*: PROCEDURE (f: FSM): INTEGER; AddCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos: INTEGER; VAR len: INTEGER); AckCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; NakCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; RejCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; ReqCI*: PROCEDURE (f: FSM; VAR p: ARRAY OF CHAR; VAR pos, len: INTEGER; mode: BOOLEAN): SHORTINT; Up*: PROCEDURE (f: FSM); Down*: PROCEDURE (f: FSM); (*		Starting*: PROCEDURE (f: FSM); *) (*		Finished*: PROCEDURE (f: FSM); *) ExtCode*: PROCEDURE (f: FSM; code, id:SHORTINT; VAR inp: ARRAY OF CHAR; pos, len: INTEGER): BOOLEAN; HDLCConfig*: HDLC.PPPUnit; params: Params; END; ParamsDesc = RECORD (HDLC.ParamsDesc) f:FSM END; String* = ARRAY StrLen OF CHAR; VAR ActTimeout*:LONGINT; ActMaxConfReqs*:INTEGER; PROCEDURE ^ Init* (f: FSM); PROCEDURE ^ LowerUp* (f: FSM); PROCEDURE ^ LowerDown* (f: FSM); PROCEDURE ^ Open* (f: FSM); PROCEDURE ^ Close* (f: FSM); PROCEDURE ^ Timeout (params: HDLC.Params); PROCEDURE ^ Input* (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveConfReq* (f: FSM; id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveConfAck* (f: FSM; id: SHORTINT; 						VAR p:  ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveConfNakRej* (f: FSM; code, id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE ^ ReceiveTermReq* (f: FSM; id: SHORTINT); PROCEDURE ^ ReceiveTermAck* (f: FSM); PROCEDURE ^ ReceiveCodeRej* (f: FSM; VAR p: ARRAY OF CHAR; 						pos, len: INTEGER); PROCEDURE ^ ProtReject* (f: FSM); PROCEDURE ^ SendConfReq* (f: FSM; retransmit: BOOLEAN); PROCEDURE ^ SendData* (f: FSM; code, id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); PROCEDURE OutLog* (text1, text2:ARRAY OF CHAR; f:FSM) ; BEGIN Debug.String(text1); Debug.Ln; IF text2 # "" THEN Debug.String(text2); Debug.Ln; END; Debug.String("protocol: "); Debug.String(f.ProtoName); Debug.String(" -  channel: "); Debug.String(f.HDLCConfig.cname); Debug.Ln; END OutLog; PROCEDURE OutCode* (code: SHORTINT); BEGIN Debug.String("code: "); CASE code OF 		  ConfReq:	Debug.String("ConfReq") | ConfAck:	Debug.String("ConfAck") | ConfNak:	Debug.String("ConfNak") | ConfRej:	Debug.String("ConfRej") | TermReq:	Debug.String("TermReq") | TermAck:	Debug.String("TermAck") | CodeRej:	Debug.String("CodeRej") | ProtRej:	Debug.String("ProtocolRej") | EchoReply: Debug.String("EchoReply") ELSE	Debug.String("*** illegal code ***"); Debug.Int(code, 4); END; Debug.Ln END OutCode; PROCEDURE GiveState*(state: SHORTINT; VAR s: String); BEGIN CASE state OF 		  Initial:		s:="Initial";	| Starting:	s:="Starting"; | Closed:		s:="Closed";	| Stopped:	s:="Stopped"; | Closing:		s:="Closing"; | Stopping:	s:="Stopping"; | ReqSent:	s:="ReqSent";	| AckRcvd:	s:="AckRcvd"; | AckSent:	s:="AckSent"; | Opened:	s:="Opened"; ELSE	s:=" *** unknown state ***"; END; END GiveState; PROCEDURE OutState* (state: SHORTINT); VAR s: String; BEGIN Debug.String("state: "); GiveState(state, s); Debug.String(s); Debug.Ln END OutState; (* Init FSM *) PROCEDURE Init* (f: FSM); BEGIN f.State := Initial;	f.Flags := {};	f.ID := 0;	(* f.reqID set later *) f.TimeoutTime := ActTimeout; f.MaxConfReqTransmits := ActMaxConfReqs; f.MaxTermTransmits := DefMaxTermReqs; f.MaxNakLoops := DefMaxNakLoops; NEW(f.params); f.params.f:=f; END Init; (* The lower layer is up *) PROCEDURE LowerUp* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.LowerUp","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Initial:	f.State := Closed | Starting: IF Silent IN f.Flags THEN f.State := Stopped ELSE SendConfReq(f, newtransmit); f.State := ReqSent	(* send an initial configure-request *) END ELSE OutLog("FSM.LowerUp","ERROR: in wrong state",f); OutState(f.State); Debug.Ln; END END LowerUp; (* The lower layer is down - cancel all timeouts and inform upper layers *) PROCEDURE LowerDown* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.LowerDown","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Closed:	f.State := Initial | Stopped:	f.State := Starting (* ; f.Starting (f) *) | Closing:	f.State := Initial; HDLC.UNTIMEOUT(f.HDLCConfig, Timeout)	(* cancel timeout *) | Stopping, ReqSent, AckRcvd, AckSent:	f.State := Starting; HDLC.UNTIMEOUT(f.HDLCConfig, Timeout)	(* cancel timeout *) | Opened:	f.Down(f); f.State := Starting ELSE OutLog("FSM.LowerDown", "ERROR: in wrong state", f); OutState(f.State); Debug.Ln 	END END LowerDown; (* Link is allowed to come up *) PROCEDURE Open* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.Open","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Initial:	f.State := Starting; (* f.Starting(f) *) | Closed: IF Silent IN f.Flags THEN f.State := Stopped ELSE SendConfReq(f, newtransmit); f.State := ReqSent;	(* send an initial configure-request *) END | Closing:	f.State := Stopping; IF Restart IN f.Flags THEN LowerDown(f); LowerUp(f) END | Stopped, Opened:	IF Restart IN f.Flags THEN LowerDown(f); LowerUp(f) END ELSE END END Open; (* Start closing connection *) PROCEDURE Close* (f: FSM); VAR p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF HDLC.debug THEN OutLog("FSM.Close","",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Starting:	f.State := Initial | Stopped:	f.State := Closed | Stopping:	f.State := Closing | ReqSent, AckRcvd, AckSent, Opened: IF f.State # Opened THEN HDLC.UNTIMEOUT(f.HDLCConfig, Timeout)	(* cancel timeout *) ELSE f.Down(f)	(* inform upper layers we're down *) END; f.Retransmits := f.MaxTermTransmits; INC(f.ID); f.reqID := f.ID; SendData(f, TermReq, f.reqID, p, StartPos, 4); HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime); DEC(f.Retransmits); f.State := Closing ELSE END END Close; (* Timeout expired *) PROCEDURE Timeout (params: HDLC.Params); VAR f: FSM; BEGIN f := params(Params).f; 	IF HDLC.debug THEN OutLog("FSM.TimeOut","TimeOut-Handler called",f); OutState(f.State); Debug.Ln; END; CASE f.State OF 		  Closing, Stopping: IF f.Retransmits <= 0 THEN	(* we've waited for an ack long enough, peer probably heard us *) IF f.State = Closing THEN f.State := Closed ELSE f.State := Stopped END; (* f.Finished(f) *) ELSE	(* send terminate-request *) INC(f.ID); f.reqID := f.ID; SendData(f, TermReq, f.reqID, f.HDLCConfig.data2, StartPos, 0); HDLC.TIMEOUT(f.HDLCConfig, Timeout, params, f.TimeoutTime); DEC(f.Retransmits) END | ReqSent, AckRcvd, AckSent: IF f.Retransmits <= 0 THEN OutLog("LOG: FSM.Timeout", "Stop: sended all TimeOuts, no answer", f); Debug.Ln; f.State := Stopped; (* IF ~(Passive IN f.Flags) THEN f.Finished(f) END *) ELSE	(* retransmit the configure-request *) SendConfReq(f, retransmit); IF f.State = AckRcvd THEN f.State := ReqSent END END ELSE IF HDLC.debug THEN OutLog("FSM.Timeout", "ERROR:in wrong state", f); OutState(f.State); Debug.Ln; END END END Timeout; (* Input packet *) PROCEDURE Input* (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR code, id: SHORTINT; size: INTEGER; BEGIN (* parse header (code, id and length). if packet too short, drop it. *) IF HDLC.debug THEN (* pe: "FSM.ReceiveData" was followed by redundant report "new Input". *) OutLog("FSM.ReceiveData","",f); OutState(f.State); Debug.Ln; Tools.OutPacket(p, pos, len); Debug.Ln; END; IF len < HeaderLen THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received short header", f); END; RETURN END; code := SHORT(ORD(p[pos])); id := SHORT(ORD(p[pos + 1])); size := Tools.GetInt(p, pos + 2); IF size < HeaderLen THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received illegal length", f); END; RETURN END; IF size < len THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received short packet", f); END; RETURN END; DEC(size, HeaderLen); INC(pos, HeaderLen); IF (f.State = Initial) OR (f.State = Starting) THEN IF HDLC.debug THEN OutLog("FSM.ReceiveData", "ERROR: Received packet in wrong state", f); OutState(f.State); Debug.Ln; END; RETURN END; (* action depends on code *) CASE code OF 		  ConfReq:	ReceiveConfReq(f, id, p, pos, size) | ConfAck:	ReceiveConfAck(f, id, p, pos, size) | ConfNak, ConfRej:	ReceiveConfNakRej(f, code, id, p, pos, size) | TermReq:	ReceiveTermReq(f, id) | TermAck:	ReceiveTermAck(f) | CodeRej:	ReceiveCodeRej(f, p, pos, size) ELSE IF ~f.ExtCode(f, code, id, p, pos, size) THEN INC(f.ID); SendData(f, CodeRej, f.ID, p, pos - HeaderLen, size + HeaderLen) END END END Input; (* Receive Configure-Request *) PROCEDURE ReceiveConfReq* (f: FSM; id: SHORTINT; 						VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR code: SHORTINT; RejectIfDisagree: BOOLEAN; BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveConfigureRequest", "", f); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln 	END; CASE f.State OF 		  Closed:	SendData(f, TermAck, id, p, StartPos, 0); RETURN	(* go away, we're closed *) | Closing, Stopping:	RETURN | Opened:	f.Down(f); SendConfReq(f, newtransmit) (* go down and restart negotiation, inform upper layers, 					send initial configure-request *) | Stopped:	SendConfReq(f, newtransmit); f.State := ReqSent; (* send initial configure-request *) ELSE END; (* pass the requested configuration options to protocol-specific code for checking *) RejectIfDisagree := f.NakLoops >= f.MaxNakLoops; code := f.ReqCI(f, p, pos, len, RejectIfDisagree); (* send the Ack, Nak or Rej to the peer *) SendData(f, code, id, p, pos, len); IF code = ConfAck THEN IF f.State = AckRcvd THEN HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); f.State := Opened; f.Up(f) ELSE f.State := AckSent; f.NakLoops := 0 END ELSE	(* we sent ConfAck or ConfRej *) IF f.State # AckRcvd THEN f.State := ReqSent END; IF code = ConfNak THEN INC(f.NakLoops) END; END END ReceiveConfReq; (* Receive Configure-Ack *) PROCEDURE ReceiveConfAck* (f: FSM; id: SHORTINT; VAR p: ARRAY OF CHAR; pos, len: INTEGER); BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveConfAck", "", f); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln END; IF (id=f.reqID) & f.AckCI(f, p, pos, len) THEN f.reqID := -1; CASE f.State OF 			  Closed, Stopped:	SendData(f, TermAck, id, p, StartPos, 0) | ReqSent:	f.State := AckRcvd; f.Retransmits := f.MaxConfReqTransmits | AckRcvd:	SendConfReq(f, newtransmit); f.State := ReqSent	(* huh?, an extra Ack? oh well... *) | AckSent:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout);	(* cancel timeout *) f.State := Opened; f.Retransmits := f.MaxConfReqTransmits; f.Up(f) | Opened:	(* go down and restart negotiation *) f.Down(f); SendConfReq(f, newtransmit); f.State := ReqSent ELSE END END END ReceiveConfAck; (* Receive Configure-Nak or Configure-Reject *) PROCEDURE ReceiveConfNakRej* (f: FSM; code, id: SHORTINT; 	VAR p: ARRAY OF CHAR; pos, len: INTEGER); BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveConfigureNak/Reject", "", f); Debug.String("id = "); Debug.Int(id, 4); Debug.String(",   reqID = "); Debug.Int(f.reqID, 4); Debug.Ln; Debug.Ln 	END; IF id # f.reqID THEN RETURN END;	(* expected ID? nope -> toss... *) IF ((code = ConfNak) & ~f.NakCI(f, p, pos, len)) OR ((code=ConfRej) & ~f.RejCI(f, p, pos, len)) THEN (* Nak/Reject is bad - ignore it *) IF HDLC.debug THEN OutLog("FSM.ReceiveConfNakRej", "ERROR: Received bad Nak/Rej", f); Debug.String("id: "); Debug.Int(f.ID, 4); Debug.Ln; OutCode(code); Debug.Ln; RETURN END END; f.reqID := -1; CASE f.State OF 		  Closed, Stopped:	SendData(f, TermAck, id, p, StartPos, 0) | ReqSent, AckSent:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); SendConfReq(f, newtransmit) (* They didn't agree to what we wanted - try another request *) (*(*pe*)	SendConfReq(f, retransmit) *) | AckRcvd:	SendConfReq(f, newtransmit); f.State := ReqSent	(* got a Nak/Reject when we had already had an Ack?? oh well... *) | Opened:	(* go down and restart negotiation *) f.Down(f); SendConfReq(f, newtransmit); f.State := ReqSent ELSE END END ReceiveConfNakRej; (* Receive Terminate-Request *) PROCEDURE ReceiveTermReq* (f: FSM; id: SHORTINT); VAR p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveTermReq", "", f); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln END; CASE f.State OF 		  AckRcvd, AckSent:	f.State := ReqSent | Opened: OutLog("FSM.ReceiveTermReq", "Terminated at peer's request", f); f.Down(f); f.Retransmits := 0; f.State := Stopping; HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime) ELSE END; SendData(f, TermAck, id, p, StartPos, 0) END ReceiveTermReq; (* Receive Terminate-Ack *) PROCEDURE ReceiveTermAck* (f: FSM); BEGIN IF HDLC.debug THEN OutLog("FSM.ReceiveTermAck", "", f); Debug.Ln; END; CASE f.State OF 		  Closing:	f.State := Closed (* ; IF f.Finished # NIL THEN f.Finished(f) END *) | Stopping:	f.State := Stopped (* ; IF f.Finished # NIL THEN f.Finished(f) END *) | AckRcvd:	f.State := ReqSent | Opened:	f.Down(f); SendConfReq(f, newtransmit) ELSE END END ReceiveTermAck; (* Receive a Code-Reject *) PROCEDURE ReceiveCodeRej* (f: FSM; VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR code, id: SHORTINT; BEGIN IF len < HeaderLen THEN IF HDLC.debug THEN OutLog("FSM.ReceiveCodeRej", "ERROR: too short", f); Debug.Ln; END; RETURN END; code := SHORT(ORD(p[pos])); id := SHORT(ORD(p[pos + 1]));	(* syslog *) IF HDLC.debug THEN OutLog("FSM.ReceiveCodeRej", "Received Code-Reject", f); OutCode(code); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Debug.Ln; END; IF f.State = AckRcvd THEN f.State := ReqSent END END ReceiveCodeRej; (* Peer doesn't speak this protocol - Treat this as a catastrophic error (RXJ-)*) PROCEDURE ProtReject* (f: FSM); VAR p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF HDLC.debug THEN OutLog("FSM.ProtReject", "", f); Debug.Ln; END; CASE f.State OF 		  Closing:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); f.State := Closed; (* IF f.Finished # NIL THEN f.Finished(f) END *) | Closed:	f.State := Closed; (* IF f.Finished # NIL THEN f.Finished(f) END *) | Stopping, ReqSent, AckRcvd, AckSent:	HDLC.UNTIMEOUT(f.HDLCConfig, Timeout); f.State := Stopped (* ; IF f.Finished # NIL THEN f.Finished(f) END *) | Stopped:	f.State := Stopped (* IF f.Finished # NIL THEN f.Finished(f) END *) | Opened:	f.Down(f); (* init restart counter, send terminate-request *) f.Retransmits := f.MaxTermTransmits; INC(f.ID); f.reqID := f.ID; SendData(f, TermReq, f.reqID, p, StartPos, 0); HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime); DEC(f.Retransmits); f.State := Stopping ELSE IF HDLC.debug THEN OutLog("FSM.ProtReject", "ERROR: in wrong state", f); OutState(f.State); Debug.Ln END END END ProtReject; (* Send a Configure-Request *) PROCEDURE SendConfReq* (f: FSM; retransmit: BOOLEAN); VAR pos: INTEGER; CILen: INTEGER; p: ARRAY HDLC.ArrayLength OF CHAR; BEGIN IF (f.State # ReqSent) & (f.State # AckRcvd) & (f.State # AckSent) THEN (* not currently negotiating - reset options *) f.ResetCI(f); f.NakLoops := 0 END; IF retransmit THEN (* new request - reset transmission counter, use new ID *) f.Retransmits := f.MaxConfReqTransmits; INC(f.ID); f.reqID := f.ID 	END; IF HDLC.debug THEN OutLog("FSM.SendConfReq", "", f); Debug.String("id: "); Debug.Int(f.reqID, 4); Debug.String("   "); OutState(f.State); Debug.Ln END; (* make up a request packet *) pos := StartPos; IF f.CILen(f) < f.HDLCConfig.MTU - HeaderLen THEN f.AddCI(f, p, pos, CILen) ELSE OutLog("FSM.SendConfReq", "ERROR: Configure Request too big", f); RETURN END; (* send the request to our peer *) SendData(f, ConfReq, f.reqID, p, pos, CILen); (* start the retransmit timer *) DEC(f.Retransmits); HDLC.TIMEOUT(f.HDLCConfig, Timeout, f.params, f.TimeoutTime); END SendConfReq; (* SendData - Create a packet with code, id and data, 	data is in p[pos .. pos+len] *) PROCEDURE SendData* (f: FSM; code, id: SHORTINT; 												VAR p: ARRAY OF CHAR; pos, len: INTEGER); VAR minpos, maxlen: INTEGER; BEGIN maxlen:=f.HDLCConfig.MTU - HeaderLen; IF len > maxlen THEN len := maxlen; END; (* adjust length (of information + padding) to be smaller than MTU *) minpos:=HDLC.HDLCHeaderLen+HeaderLen; IF pos<minpos THEN Tools.CopyString(p, pos, minpos, len); pos:=minpos; END; DEC(pos, HeaderLen); INC(len, HeaderLen); p[pos]:=CHR(code); p[pos+1]:=CHR(id); Tools.PutInt(len, p, pos+2); IF HDLC.debug THEN OutLog("FSM.SendData", "", f); OutCode(code); OutState(f.State); Debug.String("id: "); Debug.Int(id, 4); Debug.Ln; Tools.OutPacket(p, pos, len); Debug.Ln; END; HDLC.SendPacket(f.HDLCConfig, f.Protocol, p, pos, len); END SendData; BEGIN ActTimeout:=DefTimeout; ActMaxConfReqs:=DefMaxConfReqs END PPPFSM.

title: Oberon/ETH Oberon/PPPIPCP.Mod